Java BigInteger 與C# BigInteger之間的問題

最近接到一個Java代碼轉C#代碼的項目。本來就兩個函數看起來很簡單的,後來折騰了一天,終於完美收官。

碰到的第一個問題是:java的BigInteger構造函數裏面BigInteger(string,int),是字符串和進制數,.net的確是具體的整型,數字型的。

後來發現有個函數BigInteger.Parse裏面可以使用字符串類型的,就拿來直接使用。後來發現某一部分數據對,一部分數據不對。

BigInteger.Parse(hexStr, NumberStyles.HexNumber)

這下傻逼了,網上找資料查詢,找到一篇地址:https://majing.io/posts/10000005661225

原文說明如下:

在C#十六進制轉換爲十進制:

BigInteger number = BigInteger.Parse(hexString, NumberStyles.AllowHexSpecifier);
或者

BigInteger number = BigInteger.Parse(hexString, NumberStyles.HexNumber);
HexNumber是一個組合的NumberStyles,它是由AllowHexSpecifier,AllowLeadingWhite和AllowTrailingWhite組合而成,它允許字符串前後後空格。

使用BigInteger.Parse()轉換十六進制的字符串爲十進制的數字有兩個注意點:

十六進制的字符串不能以“0x”或者“&h”爲前綴
如果十六進制字符串的前兩位的數等於或者大於0x80,那麼Parse()方法會把第一位作爲符號位,即把它存儲爲負數。如果需要把此十六進制的字符串解析爲正數,需要在字符串前加上“0”。
示例

using System;
using System.Globalization;
using System.Numerics;

public class Example
{
  public static void Main()
  {
   string[] hexStrings = { "80", "E293", "F9A2FF", "FFFFFFFF", 
               "080", "0E293", "0F9A2FF", "0FFFFFFFF",  
               "0080", "00E293", "00F9A2FF", "00FFFFFFFF" };
   foreach (string hexString in hexStrings)
   {
     BigInteger number = BigInteger.Parse(hexString, NumberStyles.AllowHexSpecifier);
     Console.WriteLine("0x{0}:{1}.", hexString, number);
   }     
  }
}
輸出結果:

0x80:-128
0xE293:-7533
0xF9A2FF:-417025
0xFFFFFFFF:-1
0x080128
0x0E29358003
0x0F9A2FF16360191
0x0FFFFFFFF4294967295
0x0080128
0x00E29358003
0x00F9A2FF16360191
0x00FFFFFFFF4294967295

第二個問題是java的byte是有符號類型(java就沒有無符號類型的數據),值域:-128~127

而c#的byte是無符號類型數值,值域:0~255,在做BigInteger.ToByteArray()導致得到的數據不一致。

 使用&與運算 int num1=byte[0]&0xff 與運算一下。原理:0xff是十六進制整形(至少16位)在直接轉化爲整形時是255,相當於0x00ff,其二進制表達爲前面8個0,後面8個1.而我們知道任何數值與1與還等於其本身。但是0xff是整形至少16個位,byte只擁有8個位,與0x00ff的與運算就相當於吧byte擴充成至少16位的整形。轉換自然就OK了。但是不能用0xffff。這是爲什麼呢?如果是正數,沒有什麼問題,其實與0xff與運算分爲兩步,第一個把byte真實擴充爲至少16位的整形,擴充的方式正數前用0填位,負數用1填位。所依負數就有問題了,因爲java對於8位的負數(計算機系統負數表達形式用正數的補碼標示負數,即正數取反1變0,0變1,然後最後一位加1,這時候負數的第一位肯定是1)擴展位數時時前面是用1填充的,其實就變成0xff[byte]。0xff只是後面8位是1,其實就等於0x00ff,前面是0.與運算之後把負數系統自動擴展的1去掉了,就是一個變成正數了,但是用0xffff,如果是16位的整形,與負數與運算,就會保持不變。如果是32爲的整形,就會變成一個更大的值0x0000ff[byte]。

引用地址:https://www.cnblogs.com/edzjx/archive/2012/09/16/2687419.html

但是目前碰到的情況是不能變更java這邊的代碼。所以必須得想辦法解決c#的問題。後來想到c#有個sbye是有符號的,採用sbye[]替換bye[],轉換問題得以解決。

第三個問題,是base64的問題。

 

未完待續。

github源碼地址

 參考1:https://www.codeproject.com/Articles/276993/Base-Encoding-on-a-GPU

參考2:http://www.java2s.com/Code/CSharp/Development-Class/TheBase64utilityclassperformsbase64encodinganddecoding.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章