非常大数的对数

时间:2011-11-22 19:56:05

标签: c++ logging logarithm arbitrary-precision

我必须找到非常大的数字日志。

我在C ++中这样做

我已经实现了乘法,加法,减法,除法的功能,但是对数存在问题。我不需要代码,我需要一个简单的想法如何使用这些函数来完成它。

感谢。

P.S。 对不起,我忘了告诉你:我必须找到这个数字的唯一二进制对数

P.S. -2- 我在Wikipedia找到了:

int floorLog2(unsigned int n) {

if (n == 0)

  return -1;

int pos = 0;

if (n >= (1 <<16)) { n >>= 16; pos += 16; }

if (n >= (1 << 8)) { n >>=  8; pos +=  8; }

if (n >= (1 << 4)) { n >>=  4; pos +=  4; }

if (n >= (1 << 2)) { n >>=  2; pos +=  2; }

if (n >= (1 << 1)) {           pos +=  1; }

return pos;

}

如果我用大数字重新制作它,它会正常工作吗?

2 个答案:

答案 0 :(得分:7)

我假设你正在写自己的bignum课程。如果你只关心log2的整体结果,那很容易。记录非最重要数字的日志,并在该字节后添加8。这假设每个字节保持值0-255。这些仅在±.5范围内准确,但速度非常快。

[0][42][53] (10805 in bytes)
    log2(42) = 5
    + 8*1    = 8    (because of the one byte lower than MSB)
             = 13  (Actual: 13.39941145)

如果您的值保持基数为10位数,则表示log2(MSB)+3.32192809*num_digits_less_than_MSB

[0][5][7][6][2] (5762)
 log2(5)        =  2.321928095
 + 3.32192809*3 =  9.96578427  (because 3 digits lower than MSB)
                =  12.28771  (Actual: 12.49235395)
(only accurate for numbers with less than ~10 million digits)

如果您使用了维基百科上找到的算法,它将会非常缓慢。 (但如果你需要小数,则准确无误)

有人指出,当MSB很小时(仍然在±.5范围内,但没有更远),我的方法是不准确的,但这很容易通过简单地将前两个字节移动到一个数字来修复,记录 ,并对小于该数字的字节进行乘法运算。我相信这将在半个百分之内准确,并且仍然显着比正常对数更快。

[1][42][53] (76341 in bytes)
    log2(1*256+42) = ?
    log2(298) = 8.21916852046
    + 8*1     = 8    (because of the one byte lower than MSB)
              = 16.21916852046  (Actual: 16.2201704643)

对于10位基数,它是log2( [mostSignificantDigit]*10+[secondMostSignifcantDigit] ) + 3.32192809*[remainingDigitCount]

如果性能仍然出现问题,则可以使用log2的查找表,而不是使用完整的对数函数。

答案 1 :(得分:3)

我假设您想知道如何“手动”计算对数。所以我告诉你我为此找到了什么。

查看here,其中描述了如何手动对数。您可以将其实现为算法。 Here是“欧拉如何做到”的文章。我也发现this article很有前途。

我认为有更复杂的方法可以做到这一点,但它们非常复杂,你可能不想实现它们。