我正在尝试用大数字进行一些计算
λ: let r = 291381631919914084
λ: let t = 1165526527679656343
λ: sqrt(4 * r * r - 4 * r + 1 + 8 * t) - 2 * r + 1
1.0
答案应为8.0000...
有没有我应该用于此类计算的包裹?还是我应该在前奏中做些什么?
答案 0 :(得分:10)
正确答案确实非常接近8.0
。您正在遇到数值精度问题:使用IEEE 754("双精度")二进制64格式计算平方根,其53位精度不足以提供准确的结果在这里。
更详细地说:sqrt(4 * r * r - 4 * r + 1 + 8 * t)
的真实价值是50个有效数字:
582763263839828175.00000000000000000686385063746811
与该数量最接近的可表示的IEEE 754二进制64值是:
582763263839828224.0
...与真实值相比约为49.0。同样,值2*r
在转换为浮点时会失去精度。
您可能想通过提高精度来解决这个问题,但是在数值工作中经常会发生这种情况,在这种情况下,重新编写算法以避免(或至少改善)数值问题会更好。您计算的值的格式为sqrt(a * a + b) - a
(a = 2 * r - 1
和b = 8 * t
)。该数量可以使用b / (sqrt(a * a + b) + a)
形式重写,并且(假设a
和b
均为正数),后一个表达式将提供更准确的结果。
这里有一个快速演示,两个表达式给出了相同的结果。
Prelude> let a = 43
Prelude> let b = 7
Prelude> sqrt(a * a + b) - a
8.131845707602992e-2
Prelude> b / (sqrt(a * a + b) + a)
8.131845707603225e-2
我们使用较小的a
和b
值,因此数字问题并不是很糟糕,但请注意,最后一个问题仍然存在差异4位数。 (此处的确切值为0.081318457076032250005683932322636450
,为35位有效数字。)
将这种形式的表达式与您的值一起使用:
Prelude> let r = 291381631919914084
Prelude> let t = 1165526527679656343
Prelude> let a = 2*r - 1; b = 8*t in b / (sqrt(a*a+b) + a)
8.0
正如其他回答者所指出的,答案并非完全 8.0
,但8.0
是最接近的IEEE 754二进制64浮点值到真正的答案。
答案 1 :(得分:7)
我相信8
也不是正确答案;你给出的数字不是正方形:
Math.NumberTheory.Powers.Squares> r = 291381631919914084
Math.NumberTheory.Powers.Squares> t = 1165526527679656343
Math.NumberTheory.Powers.Squares> isSquare (4*r*r - 4*r + 1 + 8*t)
False
但是,如果你想要的话,你可以得到这个答案:
Math.NumberTheory.Powers.Squares> integerSquareRoot (4*r*r - 4*r + 1 + 8*t) - 2*r + 1
8
arithmoi包提供了这些功能。
或者,您可以根据需要获得确切答案的数字位数:
Data.Number.CReal> sqrt (4*r*r - 4*r + 1 + 8*t) - 2*r + 1 :: CReal
8.0000000000000000068638506374681082902485
numbers包提供此类型。
答案 2 :(得分:-3)
我把这些数字和公式放在Rstudio中并得到1.你确定答案是8吗?也许添加更多括号以确保您的操作顺序正确。