C#System.Numerics.BigInteger幅度估计

问题描述 投票:1回答:4

我目前正在使用以下方法来获得BigInteger的幅度估计。我很想知道是否有人可以建议一个不需要使用BigInteger.ToByteArray()的方法;

 public static long MagnitudeEstimate(BigInteger value)
 {

     byte[] array = value.ToByteArray();

     if (array.Length == 0 || (array.Length == 1 && (array[0] == 0 || array[0] == 1)))
         return 0;
     else
         return (long)(array.Length * 2.408239965);
 }
c# biginteger
4个回答
1
投票

转换为double并取对数似乎是一种简单的方法。

Math.Log10((double)bigInt)

或者只是内置的

BigInteger.Log10(bigInt)

我没有对它进行基准测试,所以我不知道它有多快。


1
投票

一个hackish解决方案。我不会用这个。

BigInteger bi = new BigInteger(long.MaxValue);

var fieldInfo = typeof(BigInteger).GetField("_bits", BindingFlags.Instance | BindingFlags.NonPublic);

var arr = (uint[])fieldInfo.GetValue(bi);
var size =  arr.Length * sizeof(uint);

0
投票

结合我的原始版本和L.B我已经确定了以下内容。虽然它不比我的原始版本快,但它更准确。

非常感谢大家的投入。

public static long MagnitudeEstimate(BigInteger value)
{
      var fieldInfo = typeof(BigInteger).GetField("_bits", BindingFlags.Instance | BindingFlags.NonPublic);
      var arr = (uint[])fieldInfo.GetValue(value);
      if (arr != null)
      {
            int totalNumBytes = arr.Length * sizeof(uint);
            int zeroBytes = 0;
            for (int i = arr.Length - 1; i >= 0; i--)
            {
                  if (arr[i] == 0)
                  {
                        zeroBytes += 4;
                        continue;
                  }
                  else if (arr[i] <= 0xFF)
                        zeroBytes += 3;
                  else if (arr[i] <= 0xFFFF)
                        zeroBytes += 2;
                  else if (arr[i] <= 0xFFFFFF)
                        zeroBytes += 1;

                  break;
            }

            return (long)((totalNumBytes - zeroBytes) * 2.408239965);
      }
      else return 0;
}

0
投票

从.NET Core 2.1开始,有一个new API: public int GetByteCount (bool isUnsigned = false);

它不会复制任何内容,可以用作非常精确的数字估计。

© www.soinside.com 2019 - 2024. All rights reserved.