自己最近做公司一个支付项目,其中用到数字的压缩,要将自己的10进制数据,压缩成更短的形式。我网上找了一个java版本的,可惜只对int类型的有效,对long类型的就转换错误了。
为了项目,自己写了个v2版本的函数,放里面补充,同时,因为c++模块也需要转换,所以也花了一晚上写了c++的版本,验证无误已经上线了。
java的
/******************************************************************** created: desc: 10进制与62进制的相互转换 author: 陈刚 purpose: 如有问题与我联系 QQ: 17448470 *********************************************************************/ package com.xxx.common.conv; import java.util.Stack; /** * * @author Administrator */ public class DigitalFor62 { private static char[] charSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); /** * 将10进制转化为62进制 * @param number * @param length 转化成的62进制长度,不足length长度的话高位补0,否则不改变什么 * @return */ public static String _10_to_62(long number, int length){ Long rest=number; Stack<Character> stack=new Stack<Character>(); StringBuilder result=new StringBuilder(0); while(rest!=0){ stack.add(charSet[new Long((rest-(rest/62)*62)).intValue()]); rest=rest/62; } for(;!stack.isEmpty();){ result.append(stack.pop()); } int result_length = result.length(); StringBuilder temp0 = new StringBuilder(); for(int i = 0; i < length - result_length; i++){ temp0.append('0'); } return temp0.toString() + result.toString(); } /** * 将62进制转换成10进制数 ,我重新写了这个函数,原先版本有问题 * * @param ident62 * @return */ public static String convertBase62ToDecimal_v2( String ident62 ) { Long dst = 0L; for(int i=0; i<ident62.length(); i++) { char c = ident62.charAt(i); for(int j=0; j<charSet.length; j++) { if(c == charSet[j]) { dst = (dst * 62) + j; break; } } } String str = String.format( "%08d", dst); return str; } /** * 将62进制转换成10进制数 * * @param ident62 * @return */ public static String convertBase62ToDecimal( String ident62 ) { int decimal = 0; int base = 62; int keisu = 0; int cnt = 0; byte ident[] = ident62.getBytes(); for ( int i = ident.length - 1; i >= 0; i-- ) { int num = 0; if ( ident[i] > 48 && ident[i] <= 57 ) { num = ident[i] - 48; } else if ( ident[i] >= 65 && ident[i] <= 90 ) { num = ident[i] - 65 + 10; } else if ( ident[i] >= 97 && ident[i] <= 122 ) { num = ident[i] - 97 + 10 + 26; } keisu = (int) java.lang.Math.pow( (double) base, (double) cnt ); decimal += num * keisu; cnt++; } return String.format( "%08d", decimal ); } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("62System=" +_10_to_62(Integer.parseInt("35174605"), 0)); System.out.println("10System=" +convertBase62ToDecimal("2NaWL")); System.out.println("10System=" +convertBase62ToDecimal_v2("00008sKrPTsBmv")); //120160524121052485 } }
c++的 digital_conv.h
/******************************************************************** created: 2016-5-25 desc: 10进制与x进制的相互转换 author: 陈刚 purpose: 如有问题与我联系 QQ: 17448470 *********************************************************************/ #pragma once #include "string_util.h" //10进制和x进制的换算 class CBaseDigitalConv { public: CBaseDigitalConv(){} virtual ~CBaseDigitalConv(){} public: //10进制转化成的x进制长度,不足nMinLen长度的话高位补0,否则不改变什么 string to_x(const string& src10, int nMinLen) { string dst; uint64_t src = CStringUtil::stringToint64(src10); while(src != 0){ int nMod = src % m_nDigital; char szTmp[2]; szTmp[0] = m_charSet[nMod]; szTmp[1] = 0; dst.append(szTmp); src = src / m_nDigital; } reverse(dst.begin(), dst.end()); string str = convMinLen(dst, nMinLen); return str; } //x进制转为10进制 string to_10(const string& srcx, int nMinLen) { uint64_t dst = 0L; for(int i=0; i<srcx.length(); i++) { char c = srcx[i]; for(int j=0; j<strlen(m_charSet); j++) { if(c == m_charSet[j]) { dst = (dst * m_nDigital) + j; break; } } } string str = convMinLen(CStringUtil::int64Tostring(dst), nMinLen); return str; } protected: static string convMinLen(const string& src, int nMinLen) { int nAddLen = nMinLen - src.length(); string strTmp; for(int i=0; i<nAddLen; i++) { strTmp += "0"; } return strTmp + src; } //初始化,设置字符集 void init(const char* charSet) { strcpy(m_charSet, charSet); m_nDigital = strlen(m_charSet); } private: char m_charSet[128]; int m_nDigital; }; //10进制和62进制的换算,如 0120160524121052485 --》 00008sKrPTsBmv class CDigitalConv62 : public CBaseDigitalConv { public: CDigitalConv62() { init("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); } virtual ~CDigitalConv62(){} }; //10进制和90进制的换算,如 0120160524121052485 --》 R;NKOY[U. class CDigitalConv90 : public CBaseDigitalConv { public: CDigitalConv90() { init("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+-=[]{}|;:,./<>?"); } virtual ~CDigitalConv90(){} }; /* 测试例子: //0120160524121052485 --》 00008sKrPTsBmv CDigitalConv62 d62; string str10 = d62.to_10("00008sKrPTsBmv", 0); str10 = d62.to_10("00008sKrPTsBmv", 19); string str62 = d62.to_x("0120160524121052485", 0); str62 = d62.to_x("0120160524121052485", 14); //0120160524121052485 --》 R;NKOY[U. CDigitalConv90 d90; str10 = d90.to_10("R;NKOY[U.", 0); string str90 = d90.to_x("0120160524121052485", 0); */
C++需要的另外一个工具类string_util.h 文件,代码如下:
static int64_t stringToint64(const string& strValue) { #ifdef WIN32 return _atoi64(strValue.c_str()); #else return atoll(strValue.c_str()); #endif } static string int64Tostring(int64_t nValue) { char sz[100]; #ifdef WIN32 sprintf(sz, "%I64u", nValue); #else sprintf(sz, "%llu", nValue); #endif return sz; }
从代码可以看出,C++的版本可以实现任意进制的转换,个性化修改一下字符集就可以了。