zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    战略威慑 51nod提高组试题
    赛艇表演 51nod提高组模拟试题
    Emiya家今天的饭 NOIP2019 (CSP?) 类DP好题 luoguP5664
    华容道题解 NOIP2013 思路题!
    (板子) 最小生成树 买礼物 luogu P1194
    (板子)并查集(递归+循环)
    校园网络 luogu P2812 (又是强联通)
    货车运输 noip2013 luogu P1967 (最大生成树+倍增LCA)
    Codeforces Round #684 (Div. 2)
    Codeforces Round #683 (Div. 2, by Meet IT)
  • 原文地址:https://www.cnblogs.com/fer-team/p/9591804.html
Copyright © 2011-2022 走看看