python-3.x - 如何防止多个小数相乘的“溢出”?
问题描述
我有一个包含 x 非常小的数字的列表,并且想要创建它们的产品。我只想使用纯 Python 或/和 numpy。
# List A with x very small numbers
A =[1.20223398e-072 1.53678559e-067 6.04813112e-041 3.26046833e-104
3.09114525e-048 7.65394632e-118 4.58886892e-209 7.02220200e-044
3.40963578e-085 2.79721084e-060 6.99320974e-052 7.65701921e-039
3.05321642e-103 2.33360119e-050 2.92905105e-044 5.13970623e-044
6.46863409e-180 1.78254565e-177 6.26061488e-068 5.86281346e-043]
#creating the product of all elements in A
np.prod(A)
输出:
0.0
这是一个问题,也许是溢出?!我尝试了什么?
- 我试图在一个循环中执行此操作 => 运行时间非常糟糕并且没有工作
输入:
prod = 1 for i in A): prod = prod * A
输出:
0.0
- 我试图按数量排序,然后从数组中乘以总是第一个和最后一个,然后是第二个和倒数第二个,倒数第三个和第三个,.... => 没有工作以太输入:
prod = 1 A.sort() for i in range(len(A)): prod = prod * (A[i]*A[-i-1])
输出:
0.0
有谁知道如何解决这个问题?
最好的问候克里斯蒂安
解决方案
底层的浮点存储不足以容纳如此小的数字,尤其是它们的乘积,乘法越多,乘积越小。
>>> A[0]*A[1]
1.8475758562723483e-139
>>> A[0]*A[1]*A[2]
1.1174381032881437e-179
>>> A[0]*A[1]*A[2]*A[3]
3.6433715465062613e-283
>>> A[0]*A[1]*A[2]*A[3]*A[4]
0.0
但是,使用这些特定数字,该产品实际上适合一种np.float128
类型:
>>> np.prod(A, dtype=np.float128)
6.439950307032109978e-1637
当然,这只是移动了目标:乘以其他数字可能会再次给你一个零。
另一种方法是在 Python 中使用该decimal
模块,这将使您在处理精确数字方面具有最大的灵活性。虽然它比 IEEE 浮点数慢得多,但应该可以工作:
>>> import decimal
>>> B = [decimal.Decimal(x) for x in A]
>>> B[0]*B[1]
Decimal('1.847575856272348173712320037E-139')
>>> B[0]*B[1]*B[2]
Decimal('1.117438103288143607857271302E-179')
>>> B[0]*B[1]*B[2]*B[3]
Decimal('3.643371546506261078793026112E-283')
>>> B[0]*B[1]*B[2]*B[3]*B[4]
Decimal('1.126219064996798351280705310E-330')
推荐阅读
- ios - iOS - 损坏的 iMessage 链接共享
- java - 无法在 Visual Studio 代码上将 Gradle 版本 7.0.2 与 java 11 一起使用
- pine-script - 基于用户输入的每日开/关限制
- asp.net - Asp.net Web 表单(非 MVC)天蓝色活动目录身份验证
- vue.js - Vue警告:属性或方法未在实例上定义,但在渲染期间引用
- python - 有没有办法只按1次就可以让方块连续移动?
- spring-boot - Spring Cloud 配置服务器 git 连接问题
- javascript - 合并两个 JavaScript 对象,添加数字而不是替换它们
- c - 为什么这段代码涉及数组和指针的行为如此?
- python - 使用 python 写入 csv 文件时遇到问题