自己最近做公司一個支付項目,其中用到數字的壓縮,要將自己的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++的版本可以實現任意進制的轉換,個性化修改一下字符集就可以了。
