Java & C# BCD編碼與十進位制轉換
阿新 • • 發佈:2018-11-09
目錄
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();
}
}
}