【发布时间】:2012-08-17 10:04:29
【问题描述】:
我正在处理 BigInteger 类,其中的数字是 2 的 10,000,000 次幂。
BigInteger Log 函数现在是我算法中最昂贵的函数,我正在拼命寻找替代方法。
由于我只需要日志的组成部分,我遇到了this answer,它在速度方面看起来很棒,但由于某种原因我没有得到准确的值。我不关心小数部分,但我确实需要得到一个准确的整数部分,无论值是下限还是上限,只要我知道哪个。
这是我实现的功能:
public static double LogBase2 (System.Numerics.BigInteger number)
{
return (LogBase2(number.ToByteArray()));
}
public static double LogBase2 (byte [] bytes)
{
// Corrected based on [ronalchn's] answer.
return (System.Math.Log(bytes [bytes.Length - 1], 2) + ((bytes.Length - 1) * 8));
}
这些值现在非常准确,除了极端情况。值 7 到 7.99999、15 到 15.9999、23 到 23.9999 31 到 31.9999 等返回 -Infinity。这些数字似乎围绕字节边界旋转。知道这里发生了什么吗?
例子:
LogBase2( 1081210289) = 30.009999999993600 != 30.000000000000000
LogBase2( 1088730701) = 30.019999999613300 != 30.000000000000000
LogBase2( 2132649894) = 30.989999999389400 != 30.988684686772200
LogBase2( 2147483648) = 31.000000000000000 != -Infinity
LogBase2( 2162420578) = 31.009999999993600 != -Infinity
LogBase2( 4235837212) = 31.979999999984800 != -Infinity
LogBase2( 4265299789) = 31.989999999727700 != -Infinity
LogBase2( 4294967296) = 32.000000000000000 != 32.000000000000000
LogBase2( 4324841156) = 32.009999999993600 != 32.000000000000000
LogBase2( 545958373094) = 38.989999999997200 != 38.988684686772200
LogBase2( 549755813887) = 38.999999999997400 != 38.988684686772200
LogBase2( 553579667970) = 39.009999999998800 != -Infinity
LogBase2( 557430119061) = 39.019999999998900 != -Infinity
LogBase2( 561307352157) = 39.029999999998300 != -Infinity
LogBase2( 565211553542) = 39.039999999997900 != -Infinity
LogBase2( 569142910795) = 39.049999999997200 != -Infinity
LogBase2( 1084374326282) = 39.979999999998100 != -Infinity
LogBase2( 1091916746189) = 39.989999999998500 != -Infinity
LogBase2( 1099511627775) = 39.999999999998700 != -Infinity
【问题讨论】:
-
这些都没有高估日志只是一个巨大的巧合吗?我原以为只需要 LSB > MSB。
-
哦等等,有几个。不过,我预计它会接近 50/50。
-
嗯...当整数达到 8 的倍数时,BigInteger 似乎保留了一个额外的最高有效字节? -Infinity 是 Log(0) 的结果。
-
额外字节确保正整数的最高有效位为 0。
标签: c# .net biginteger logarithm