我目前正在使用以下方法来获得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);
}
转换为double并取对数似乎是一种简单的方法。
Math.Log10((double)bigInt)
或者只是内置的
BigInteger.Log10(bigInt)
我没有对它进行基准测试,所以我不知道它有多快。
一个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);
结合我的原始版本和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;
}
从.NET Core 2.1开始,有一个new API: public int GetByteCount (bool isUnsigned = false);
它不会复制任何内容,可以用作非常精确的数字估计。