一减一个小数等于一个?处理小数字

时间:2014-03-06 03:47:31

标签: python numpy floating-accuracy

标题是自我解释的。这里发生了什么?我怎么能不发生这种情况?我是否真的必须改变我的所有单位(这是一个物理问题),这样我才能得到一个足够大的答案,即python不会将1-x转为1?

代码:

import numpy as np
import math

vel=np.array([5e-30,5e-30,5e-30])

c=9.7156e-12

def mag(V):
    return math.sqrt(V[0]**2+V[1]**2+V[2]**2)

gam=(1-(mag(vel)/c)**2)**(-1/2)

print(mag(vel))
print(mag(vel)**2)
print(mag(vel)**2/(c**2))
print(1-mag(vel)**2/(c**2))
print(gam)

输出:

>>> (executing lines 1 to 17 of "<tmp 1>")
8.660254037844386e-30
7.499999999999998e-59
7.945514251743055e-37
1.0
1.0
>>> 

2 个答案:

答案 0 :(得分:1)

在python中decimal可能有用,也许mpmath

正如此SO article

中所讨论的那样

如果您愿意使用Java(而不是python),您可以使用BigDecimal,或apfloatJScience

8.66e-30仅使用3个sig,但要说明需要超过30的1个减号。任何超过16个有效数字,您需要使用其他东西来表示数字,例如非常长的字符串。但是用长串做数学是很困难的。您还可以对很长的字节值数组执行二进制计算。可以使字节值表示由您选择的比例因子修改的非常大的整数值。因此,如果您可以支持大于1E60的整数,那么您可以交替缩放该值,以便您可以表示1E-60,最大值为1.您可以使用大约200位或25个字节,以及400位,您应该能够精确地表示1E60到1E-60的整个范围。可能已经存在可以执行此类型计算的实用程序,这些实用程序可用于数学或安全性工作的人员,因为他们可能希望将PI表示为一千个地方,例如,您无法使用双重执行。

另一个有用的技巧是使用比例因子。也就是说,在原始坐标空间中,您无法进行减法,因为数字将无法表示值。但是,如果您假设如果进行小的调整而不是同时关注大的调整,那么您可以对数据执行转换。例如,您从数字中减去1。然后你可以将1-1E-60表示为-1E-60。您可以在变换空间中非常精确地执行尽可能多的操作,但要充分了解如果您尝试将它们从变换空间转换回来,它们将会丢失为无关紧要。放大地图时,这种策略非常有用。对于单精度浮点DirectX计算,以纬度和经度为单位对千分尺进行调整将不起作用。但是,您可以在放大时暂时更改比例,以便操作正常运行。

因此,复杂的数字可以用大数字加上代表小规模调整的第二个数字来表示。因此,例如,如果您在double中有16位数字,则可以使用第一个数字表示值的大部分,例如1到1E16,第二个数字表示额外的小部分。除了使用16位数字可能会因双重能够准确表示大值的错误而调情,因此您可能只使用15或14左右才能保证安全。

1234567890.1234567890

成为

1.234567890E9 + 1.23456789E-1.

基本上你的精确度越高,你的复数就越多。但是,当每个术语或多或少在数学上独立时,这类事情的效果非常好,如果您必须进行大量的严格计算,那么在这些值之间进行簿记可能更多的是痛苦而不是值得。

答案 1 :(得分:0)

我认为你不会得到你期望的结果,因为你正在处理计算机数学限制。关于这种计算的事情是没有人可以避免这个错误,除非你制作/找到一些具有无限(理论上)小数的模型并且你可以使用它们。如果这对你要解决的问题太多了,也许你只需要小心并尝试做任何你需要的事情,但试图在计算中处理这些错误。

有很多参考书目有许多不同的方法来处理计算中的错误,这些方法有助于避免但最大限度地减少这些错误。

希望我的回答有所帮助,不要让你失望..