haskell - 787有什么特别之处?

标签 haskell integer-arithmetic

在 ghci 中,使用 arithmoi包裹:

Math.NumberTheory.Powers.General> :set +s
Math.NumberTheory.Powers.General> integerRoot 786 ((10^32)^786)
100000000000000000000000000000000
(0.04 secs, 227,064 bytes)
Math.NumberTheory.Powers.General> integerRoot 787 ((10^32)^787)

五分钟后,它仍然没有回应。为什么需要这么长时间?

(从一些临时测试来看,对于所有大于 787 的选项,它似乎很慢,而对于所有小于 787 的选项,它似乎很快。)

最佳答案

算术 implements integerRoot 通过得到一个初始的近似根并用牛顿法改进它的猜测。对于 (1032)786,第二个近似值得到了一个非常好的起点:

> appKthRoot 786 ((10^32)^786)
100000000000000005366162204393472

对于 (1032)787,第二个近似值的起点非常糟糕。就像,真的很糟糕。
> appKthRoot 787 ((10^32)^787)   
1797693134862315907729305190789024733617976978942306572734300811577326758055009
6313270847732240753602112011387987139335765878976881441662249284743063947412437
7767893424865485276302219601246094119453082952085005768838150682342462881473913
110540827237163350510684586298239947245938479716304835356329624224137216

它实际上得到了从那里开始的所有内容的近似值。
> length $ nub [appKthRoot x ((10^32)^x) | x <- [787..1000]]
1

无论如何,输入 the important parts of appKthRoot ,我们得到:
> let h = 106; k = 786; n = (10^32)^k; !(I# s) = h * k - k in floor (scaleFloat (h - 1) (fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double))
100000000000000005366162204393472

> let h = 106; k = 787; n = (10^32)^k; !(I# s) = h * k - k in floor (scaleFloat (h - 1) (fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double))
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216

看看 scaleFloat 中发生了什么:
> let h = 106; k = 786; n = (10^32)^k; !(I# s) = h * k - k in fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double
2.465190328815662

> let h = 106; k = 787; n = (10^32)^k; !(I# s) = h * k - k in fromInteger (n `shiftRInteger` s) ** (1/fromIntegral k) :: Double
Infinity

是的,就可以了。 (1032)786 ÷ 282530 ≈ 21023.1 适合 double ,但 (1032)787 ÷ 282635 ≈ 21024.4 不适合。

关于haskell - 787有什么特别之处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45067989/

相关文章:

haskell - 在 Haskell 中使用什么来代替主循环?

haskell - 如何将多态数据类型转换为单个元素列表

parsing - 应用仿函数 : <*> and partial application, 它是如何工作的

python - 如何在整数运算中执行上限除法?

c - 等效于两个按位运算

haskell - Haskell 是否有某种数字转换为科学格式?

algorithm - 简单的行转置密码

performance - 计算百分比的浮点乘法的快速替代方法

algorithm - 嵌套循环的第一项和最后一项,从非零索引开始的算术级数之和

仅使用整数常量表达式计算 sqrt(SIZE_MAX+1),以适应奇怪的 ABI