【问题标题】:Java's BigInteger C# in Base 32Java 在 Base 32 中的 BigInteger C#
【发布时间】:2016-12-15 20:35:24
【问题描述】:

如何将下面的 Java 行转换为 C#。它生成一个 130 位大小的随机 BigInteger,将其转换为以 32 为底的字符串(即 不是十进制),然后对字符串进行操作:

new BigInteger(130, new SecureRandom()).toString(32).replace("/", "w").toUpperCase(Locale.US);

如何在 C# 中实现这一点?

  • 生成一个随机的 130 位 BigInteger
  • 将其转换为以 32 为底的字符串

就随机 BigInteger 而言,我有这个功能:

static BigInteger RandomInteger(int bits)
{
            RNGCryptoServiceProvider secureRandom = new RNGCryptoServiceProvider();
            // make sure there is extra room for a 0-byte so our number isn't negative
            // in the case that the msb is set
            var bytes = new byte[bits / 8 + 1];
            secureRandom.GetBytes(bytes);
            // mask off excess bits
            bytes[bytes.Length - 1] &= (byte)((1 << (bits % 8)) - 1);
            return new BigInteger(bytes);
}

取自未解决基数 32 转换的问题:Equivalent of Java's BigInteger in C#

但是我不确定该函数是否也正确。

我目前的 C# 代码,RandomInteger 是上面描述的函数:

RandomInteger(130).ToString().Replace("/","w").ToUpper(CultureInfo.GetCultureInfo("en-US"));

【问题讨论】:

  • 不清楚你在问什么。与其提供一个不完整的 Java 示例供其他人为您翻译,不如提供一个很好的 minimal reproducible example 来显示您目前拥有的 C# 代码,解释该代码的作用以及您希望它做什么反而。还要解释为什么stackoverflow.com/questions/21002856/… 不能完全解决您的问题。
  • @PeterDuniho,我补充了为什么它不能完全解决我的担忧和我的 C# 代码。
  • 很清楚:如何在 C# 中生成转换为 base 32 的 130 位随机 BigInteger?
  • FWIW,@hl3mukkel 的实现确实更好。 C# 的 BigInteger 期望字节数组是二进制补码,如果设置了最高有效字节的最高位,则将其解释为负数,这对随机数不利。所以他在顶部添加了至少一个零字节。他对数组大小的计算也更好。

标签: java c# random biginteger base32


【解决方案1】:

上面的代码有很多错误,如果位是完整的,最后一个数字会被完全屏蔽掉,并且这个数字有可能变成正数,因为新的 BigInteger(byte[]) 重载需要一个小端序有符号数,所以你必须在它前面加上一个 0 字节

    static BigInteger RandomInteger(int bits)
    {
        var bytes = new byte[(bits + 7) / 8 + 1];

        using (var rng = new RNGCryptoServiceProvider())
            rng.GetBytes(bytes, 0, bytes.Length - 1);

        var remainingBits = bits % 8;

        if (remainingBits > 0)
            bytes[bytes.Length - 2] &= (byte)((1 << remainingBits) - 1);

        return new BigInteger(bytes);
    }

我想这会起作用

【讨论】:

  • 您在此处描述的不是答案,也不包括 base 32 转换。这应该是一条评论
  • 它是 little-endian 的事实没有问题,但 BigInteger 需要一个二进制补码字节数组这一事实。这就是为什么你在前面加上一个 0 作为最重要的字节,我猜,所以它总是被解释为正数?你的版本确实更好。我认为这是一个(部分)答案。
【解决方案2】:

Base 32 字符串

这就是我将转换为 base 32 的方式。请注意,我无法在此处进行测试,而且我的 C# 有点生疏,但我认为以下内容应该足以让您继续前进(如果有人看到语法错误) ,请编辑掉):

static string BigIntegerToString32(BigInteger bi)
{
    // Obvious shortcut -- avoids problems later on.
    if (bi == BigInteger.Zero)
        return("0");

    readonly char[] digits = new char[] { 
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
        'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V'
    };

    // Only work with positive BigInteger.
    BigInteger value = BigInteger.Abs(bi);

    // Collects one digit on each iteration.
    StringBuilder result = new StringBuilder();

    // This value is needed more often -- only converted once.
    BigInteger thirtyOne = 0x1F;

    while (value > BigInteger.Zero)
    {   
        // get next digit: value % 32  
        result.Insert(0, digits[(int)(value & thirtyOne)]);

        // shift out last digit: value = value / 32
        value >>= 5;
    }

    // prepend '-' if negative
    if (bi < BigInteger.Zero)
        result.Insert(0, '-');

    return result.ToString();
}

请注意,对于巨大的BigIntegers,使用更快但更复杂的算法可能是有意义的(就像我在我的 Delphi BigInteger 实现中所做的那样),尽管这可能或多或少是 C# 的 BigInteger (它不使用更复杂的例程来处理大型 BigIntegers,AFAIK,与 Java 不同)对于 base 10 也是如此。

随机 130 位 BigInteger

@hl3mukkel 的答案在生成n 位随机BigInteger 方面比您找到并发布的代码要好得多,因此请使用他的代码生成这样的BigInteger

【讨论】:

    猜你喜欢
    • 2012-07-01
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多