【问题标题】:Logarithm of the very-very large number非常非常大数的对数
【发布时间】:2011-11-22 19:56:05
【问题描述】:

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

我在 C++ 中做到这一点

我已经做了一个乘、加、减、除的函数,但是对数有问题。我不需要代码,我需要一个简单的idea如何使用这些函数。

谢谢。

附: 抱歉,我忘了告诉你:我必须只找到那个数字的二进制对数

附注-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;

}

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

【问题讨论】:

  • 为什么不调用log函数呢?这是作业吗?
  • 来自 100000000000000000000000000000 的通话记录功能?!这可能吗?
  • 绝对。通过 1e300 即可顺利登录。
  • 嗯...谢谢,但我会遇到问题,因为我的长数字存储在 char 数组中...如何以 1e300 形式传递函数?
  • 不要将数字存储为文本。将它们转换为数字。在这种情况下,您要转换为 double。请不要告诉我你为char*写了加法和乘法例程!

标签: c++ logging logarithm arbitrary-precision


【解决方案1】:

我假设您正在编写自己的 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 以内,但不会更远),我的方法是不准确的,但这很容易解决,只需将前两个字节转换为一个数字,获取日志那个,并对小于该数字的字节进行乘法运算。我相信这将在 0.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 使用查找表,而不是使用完整的对数函数。

【讨论】:

  • 感谢您查看我的问题。我相信您提供的答案值得继续关注,并且可能会帮助其他寻求 .NET 视角的人。再次感谢。
  • @RaheelKhan:已经存在的其他答案更快,并使用相同的算法。他们已经提供了很好的 .NET 实现,不需要我的错误:D
  • 这不是精确到小数点,以 10 位为基数。有解决办法吗?
  • 对于基数为 10 位的数字,它是 log2( [mostSignificantDigit]*10+[secondMostSignifcantDigit] ) + 3.32192809*[remainingDigitCount]。您还可以使用 *100 并计算三位数的对数,以进一步提高准确性。唯一的技巧是你必须确保你有足够的数字,但这很简单。
【解决方案2】:

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

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

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

【讨论】:

  • 谢谢,但我认为使用这些方法进行计算需要很长时间,因为我有一个问题只是一个二进制对数。我可以这样做吗?:en.wikipedia.org/wiki/Binary_logarithm
  • @KamilHismatullin:你能做到吗?是的。会不会很慢?哦,是的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-18
  • 2019-12-14
  • 1970-01-01
相关资源
最近更新 更多