1. 程式人生 > >Java & C# BCD編碼與十進位制轉換

Java & C# BCD編碼與十進位制轉換

目錄

BCD碼介紹

 Java版本互轉工具

C#版本互轉工具


BCD碼介紹

  • BCD碼(Binary-Coded Decimal‎)亦稱二進碼十進數或二-十進位制程式碼。用4位二進位制數來表示1位十進位制數中的0~9這10個數碼。是一種二進位制的數字編碼形式,用二進位制編碼的十進位制程式碼。BCD碼這種編碼形式利用了四個位元來儲存一個十進位制的數碼,使二進位制和十進位制之間的轉換得以快捷的進行。這種編碼技巧最常用於會計系統的設計裡,因為會計制度經常需要對很長的數字串作準確的計算。相對於一般的浮點式記數法,採用BCD碼,既可儲存數值的精確度,又可免卻使電腦作浮點運算時所耗費的時間。此外,對於其他需要高精確度的計算,BCD編碼亦很常用。
  • BCD碼是四位二進位制碼, 也就是將十進位制的數字轉化為二進位制, 但是和普通的轉化有一點不同, 每一個十進位制的數字0-9都對應著一個四位的二進位制碼,對應關係如下: 十進位制0 對應 二進位制0000 ;十進位制1 對應二進位制0001 ....... 9 1001 接下來的10就有兩個上述的碼來表示 10 表示為00010000 也就是BCD碼是遇見1001就產生進位,不象普通的二進位制碼,到1111才產生進位10000
  • 在Java通訊應用中,往往我們接收到資料流,而流是BCD編碼後的。因此我們要轉碼來獲得我們想要的十進位制資料。下面的程式碼是BCD編碼的資料流與十進位制的轉換,僅供參考。

常用BCD碼

十進位制數 8421碼 5421碼 2421碼 餘3碼 餘3迴圈碼
0 0000 0000 0000 0011 0010
1 0001 0001 0001 0100 0110
2 0010 0010 0010 0101 0111
3 0011 0011 0011 0110 0101
4 0100 0100 0100 0111 0100
5 0101 1000 1011 1000 1100
6 0110 1001 1100 1001 1101
7 0111 1010 1101 1010 1111
8 1000 1011 1110 1011 1110
9 1001 1100 1111 1100 1010

 Java版本互轉工具

package com.util;  
  
/** 
 * 編碼工具類 
 *  
 * @author 崔素強 
 * @see BCD與十進位制的轉換 
 */  
public class BCDDecode {  
    /** 
     * @功能:測試用例 
     * @引數: 引數 
     */  
    public static void main(String[] args) {  
        byte[] b = str2Bcd("2010");  
        System.out.println(bcd2Str(b));  
    }  
  
    /** 
     * @功能: BCD碼轉為10進位制串(阿拉伯資料) 
     * @引數: BCD碼 
     * @結果: 10進位制串 
     */  
    public static String bcd2Str(byte[] bytes) {  
        StringBuffer temp = new StringBuffer(bytes.length * 2);  
        for (int i = 0; i < bytes.length; i++) {  
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));  
            temp.append((byte) (bytes[i] & 0x0f));  
        }  
        return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp  
                .toString().substring(1) : temp.toString();  
    }  
  
    /** 
     * @功能: 10進位制串轉為BCD碼 
     * @引數: 10進位制串 
     * @結果: BCD碼 
     */  
    public static byte[] str2Bcd(String asc) {  
        int len = asc.length();  
        int mod = len % 2;  
        if (mod != 0) {  
            asc = "0" + asc;  
            len = asc.length();  
        }  
        byte abt[] = new byte[len];  
        if (len >= 2) {  
            len = len / 2;  
        }  
        byte bbt[] = new byte[len];  
        abt = asc.getBytes();  
        int j, k;  
        for (int p = 0; p < asc.length() / 2; p++) {  
            if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {  
                j = abt[2 * p] - '0';  
            } else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {  
                j = abt[2 * p] - 'a' + 0x0a;  
            } else {  
                j = abt[2 * p] - 'A' + 0x0a;  
            }  
            if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {  
                k = abt[2 * p + 1] - '0';  
            } else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {  
                k = abt[2 * p + 1] - 'a' + 0x0a;  
            } else {  
                k = abt[2 * p + 1] - 'A' + 0x0a;  
            }  
            int a = (j << 4) + k;  
            byte b = (byte) a;  
            bbt[p] = b;  
        }  
        return bbt;  
    }  
}  

C#版本互轉工具

using System;
using System.Collections.Generic;
using System.Text;

namespace Base
{
    public class BCDHelper
    {
        /// <summary>
        /// 用BCD碼壓縮數字字串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] StrToBCD(string str)
        {
            return StrToBCD(str, str.Length);
        }
        public static byte[] StrToBCD(string str, int numlen)
        {
            while (str.Length < numlen)
            {
                str = "0" + str;
            }
            return ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes(str), 0, numlen);
        }

        /// <summary>
        /// 用BCD碼壓縮數字字串
        /// </summary>
        /// <param name="NumBitByte"></param>
        /// <param name="offset">偏移量</param>
        /// <param name="numlen">數字字串位數</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static byte[] ByteArrayToBCD(byte[] NumBitByte, int offset, int numlen)
        {
            //8位的ascii碼
            int Num4Len = (numlen + 1) / 2 - 1;
            byte[] Num4bitByte = new byte[Num4Len + 1];
            Num4bitByte[Num4Len] = 0;
            for (int i = 0; i <= numlen - 1; i++)
            {
                byte num = 0;

                if (i + offset >= NumBitByte.Length)
                {
                    //num = 255;
                    num = 0;
                }
                else
                {
                    num = Convert.ToByte(NumBitByte[i + offset] - 0x30);
                }

                if (i % 2 == 0)
                {
                    Num4bitByte[i / 2] = Convert.ToByte((Num4bitByte[i / 2] & 0xf) | ((num << 4) & 0xFF));
                }
                else
                {
                    Num4bitByte[i / 2] = Convert.ToByte((Num4bitByte[i / 2] & 0xf0) | num);
                }
            }

            return Num4bitByte;
        }
        /// <summary>
        /// BCD轉int
        /// </summary>
        /// <param name="bcdNum"></param>
        /// <param name="offset">偏移量</param>
        /// <param name="numlen">數字字串位數</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static int bcdToInt(byte[] bcdNum, int offset, int numlen)
        {
            return Convert.ToInt32(bcdToString(bcdNum, offset, numlen));
        }



        /// <summary>
        /// BCD轉字串
        /// </summary>
        /// <param name="bcdNum"></param>
        /// <param name="offset">偏移量</param>
        /// <param name="numlen">數字字串位數</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string bcdToString(byte[] bcdNum, int offset, int numlen)
        {
            string retString = "";
            int res;
            var len = Math.DivRem(numlen, 2, out res);
            if (res != 0)
            {
                len++;
            }

            for (int i = 0; i < len; i++)
            {
                retString += ((bcdNum[i + offset] & 0xf0) >> 4).ToString("x");
                retString += (bcdNum[i + offset] & 0xf).ToString("x");
            }



            //Dim byteChar As Byte() = New Byte(length - 1) {}
            //Dim tempHigh As Byte = 0, tempLow As Byte = 0
            //Dim i As Integer = 0
            //While tempHigh <> &HF AndAlso tempLow <> &HF0
            //    tempHigh = Convert.ToByte(bcdNum(i + offset) And &HF0)
            //    '取出高四位;
            //    tempHigh = Convert.ToByte(tempHigh >> 4)
            //    tempLow = Convert.ToByte((bcdNum(i + offset) And &HF) << 4)
            //    byteChar(i) = Convert.ToByte(tempLow Or tempHigh)
            //    i += 1
            //End While
            //Dim HexString As String() = BitConverter.ToString(byteChar).Trim().Split("-"c)
            //For Each str As String In HexString
            //    retString += str.Trim()
            //Next
            //Dim LastIndex As Integer = retString.IndexOf("F"c)
            //retString = retString.Substring(0, LastIndex)

            return retString.ToLower().Replace("f", "");
        }

        /// <summary>
        /// BCD碼轉小時分鐘
        /// date:2012-12-18
        /// author:guozh
        /// </summary>
        /// <param name="data"></param>
        /// <param name="offset">偏移位</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static System.DateTime Bcd2ToDateTime(byte[] data, int offset)
        {
            Int32 hour = default(Int32);
            Int32 minute = default(Int32);
            hour = Convert.ToInt32(bcdToString(data, offset, 2));
            minute = Convert.ToInt32(bcdToString(data, offset + 1, 2));
            return new System.DateTime(0000, 00, 00, hour, minute, 00);
        }

        /// <summary>
        /// BCD碼轉日期
        /// </summary>
        /// <param name="data"></param>
        /// <param name="offset">偏移位</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static System.DateTime Bcd3ToDateTime(byte[] data, int offset)
        {
            Int32 year = default(Int32);
            Int32 month = default(Int32);
            Int32 day = default(Int32);
            year = Convert.ToInt32("20" + bcdToString(data, offset, 2));
            month = Convert.ToInt32(bcdToString(data, offset + 1, 2));
            day = Convert.ToInt32(bcdToString(data, offset + 2, 2));
            if (day == 0 || month == 0)
            {
                return DateTime.MinValue;
            }
            return new System.DateTime(year, month, day);
        }
        public static System.DateTime Bcd4ToDateTime(byte[] data, int offset)
        {
            Int32 year = default(Int32);
            Int32 month = default(Int32);
            Int32 day = default(Int32);
            try
            {
                year = Convert.ToInt32(bcdToString(data, offset, 4));
                month = Convert.ToInt32(bcdToString(data, offset + 2, 2));
                day = Convert.ToInt32(bcdToString(data, offset + 3, 2));
            }
            catch
            {
            }
            if (day == 0 || month == 0)
            {
                return DateTime.MinValue;
            }
            return new System.DateTime(year, month, day);
        }
        public static System.DateTime Bcd5ToDateTime(byte[] data, int offset)
        {
            var year = Convert.ToInt32("20" + bcdToString(data, offset, 2));
            var month = Convert.ToInt32(bcdToString(data, offset + 1, 2));
            var day = Convert.ToInt32(bcdToString(data, offset + 2, 2));
            var hour = Convert.ToInt32(bcdToString(data, offset + 3, 2));
            var minute = Convert.ToInt32(bcdToString(data, offset + 4, 2));
            if (day == 0 || month == 0)
            {
                return DateTime.MinValue;
            }
            return new DateTime(year, month, day, hour, minute, 0);
        }
        /// <summary>
        /// BCD碼轉時間格式
        /// </summary>
        /// <param name="data"></param>
        /// <param name="offset">偏移位</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static System.DateTime Bcd6ToDateTime(byte[] data, int offset)
        {
            try
            {
                if (data.Length < offset + 6)
                {
                    return DateTime.MinValue;
                }
                int year;// = Convert.ToInt32("20" + bcdToString(data, offset, 2));
                if (!int.TryParse("20" + bcdToString(data, offset, 2), out year))
                {
                    return DateTime.MinValue;
                }
                int month;// = Convert.ToInt32(bcdToString(data, offset + 1, 2));
                if (!int.TryParse(bcdToString(data, offset + 1, 2), out month))
                {
                    return DateTime.MinValue;
                }
                int day;// = Convert.ToInt32(bcdToString(data, offset + 2, 2));
                if (!int.TryParse(bcdToString(data, offset + 2, 2), out day))
                {
                    return DateTime.MinValue;
                }
                int hour;// = Convert.ToInt32(bcdToString(data, offset + 3, 2));
                if (!int.TryParse(bcdToString(data, offset + 3, 2), out hour))
                {
                    return DateTime.MinValue;
                }
                int minute;// = Convert.ToInt32(bcdToString(data, offset + 4, 2));
                if (!int.TryParse(bcdToString(data, offset + 4, 2), out minute))
                {
                    return DateTime.MinValue;
                }
                int second;// = Convert.ToInt32(bcdToString(data, offset + 5, 2));
                if (!int.TryParse(bcdToString(data, offset + 5, 2), out second))
                {
                    return DateTime.MinValue;
                }
                if (day == 0 || month == 0 || month > 12 || day > 31 || hour > 24 || minute > 60 || second > 60)
                {
                    return DateTime.MinValue;
                }
                return new DateTime(year, month, day, hour, minute, second);
            }
            catch
            {
                return DateTime.MinValue;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        public static System.DateTime Bcd7ToDateTime(byte[] data, int offset)
        {

            var year = Convert.ToInt32(bcdToString(data, offset, 4));
            var month = Convert.ToInt32(bcdToString(data, offset + 2, 2));
            var day = Convert.ToInt32(bcdToString(data, offset + 3, 2));
            var hour = Convert.ToInt32(bcdToString(data, offset + 4, 2));
            var minute = Convert.ToInt32(bcdToString(data, offset + 5, 2));
            var second = Convert.ToInt32(bcdToString(data, offset + 6, 2));
            if (day == 0 || month == 0 || year == 0)
            {
                return DateTime.MinValue;
            }
            return new DateTime(year, month, day, hour, minute, second);
        }
        /// <summary>
        /// 小時分鐘轉BCD碼
        /// date:2012-12-18
        /// author:guozh
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static byte[] DateTimeToBcd2(System.DateTime dt)
        {
            List<byte> lst = new List<byte>();
            //StringBuilder sb = new StringBuilder();
            //sb.Append(dt.Hour.ToString("D2"));
            //sb.Append(dt.Minute.ToString("D2"));
            lst.AddRange(StrToBCD(dt.ToString("HHmm")));
            return lst.ToArray();
        }
        /// <summary>
        /// 日期轉BCD碼
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static byte[] DateTimeToBcd3(System.DateTime dt)
        {

            List<byte> lst = new List<byte>();

            //StringBuilder sb = new StringBuilder();
            //sb.Append((dt.Year - 2000).ToString("D2"));
            //sb.Append(dt.Month.ToString("D2"));
            //sb.Append(dt.Day.ToString("D2"));
            lst.AddRange(StrToBCD(dt.ToString("yyMMdd")));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Year - 2000).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Month).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Day).ToString()), 0, 2));

            return lst.ToArray();
        }
        public static byte[] DateTimeToBcd4(System.DateTime dt)
        {
            List<byte> lst = new List<byte>();
            StringBuilder sb = new StringBuilder();
            sb.Append((dt.Year).ToString("D4"));
            sb.Append(dt.Month.ToString("D2"));
            sb.Append(dt.Day.ToString("D2"));
            lst.AddRange(StrToBCD(sb.ToString()));
            return lst.ToArray();
        }
        public static byte[] DateTimeToBcd5(System.DateTime dt)
        {
            List<byte> lst = new List<byte>();
            var strTime = dt.ToString("yyMMddHHmm");
            lst.AddRange(StrToBCD(strTime));

            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Year - 2000).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Month).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Day).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Hour).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Minute).ToString()), 0, 2));
            return lst.ToArray();
        }
        public static byte[] DateTimeToBcd6(System.DateTime dt)
        {
            try
            {
                List<byte> lst = new List<byte>();
                var strTime = dt.ToString("yyMMddHHmmss");
                lst.AddRange(StrToBCD(strTime));

                //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Year - 2000).ToString()), 0, 2));
                //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Month).ToString()), 0, 2));
                //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Day).ToString()), 0, 2));
                //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Hour).ToString()), 0, 2));
                //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Minute).ToString()), 0, 2));
                //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Second).ToString()), 0, 2));

                return lst.ToArray();
            }
            catch (System.Exception ex)
            {
                
                return new byte[] { 0, 0, 0, 0, 0, 0 };
            }
        }
        public static byte[] DateTimeToBcd7(System.DateTime dt)
        {
            List<byte> lst = new List<byte>();


            StringBuilder sb = new StringBuilder();
            sb.Append(dt.Year.ToString("D4"));
            sb.Append(dt.Month.ToString("D2"));
            sb.Append(dt.Day.ToString("D2"));
            sb.Append(dt.Hour.ToString("D2"));
            sb.Append(dt.Minute.ToString("D2"));
            sb.Append(dt.Second.ToString("D2"));
            lst.AddRange(StrToBCD(sb.ToString()));

            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes(dt.Year.ToString()), 0, 4));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Month).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Day).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Hour).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Minute).ToString()), 0, 2));
            //lst.AddRange(ByteArrayToBCD(System.Text.Encoding.ASCII.GetBytes((dt.Second).ToString()), 0, 2));

            return lst.ToArray();
        }
    }
}

參考文章:http://cuisuqiang.iteye.com/blog/1429956