Vin*_*nce 5 dynamic-languages scientific-computing
我正在学习C,并且出现了保护数字和舍入错误的想法.脚本语言的实践者(我在这里想到Python和Perl)需要担心这些东西吗?如果他们正在做科学编程怎么办?
jro*_*way 10
这取决于. doubles无处不在,所以如果你用双打做数学,你会遇到任何语言的同样问题.如果你使用原生的任意精度类型,那么不,这不是问题.考虑:
use Math::BigFloat;
my $big = Math::BigFloat->new("1_000_000_000_000_000_000_000");
my $small = Math::BigFloat->new("0.000000000000000000000000001");
print $big + $small;
Run Code Online (Sandbox Code Playgroud)
(或者,如果你真的想要隐藏正在发生的事情:
use bignum;
print 1_000_000_000_000_000_000_000 + 0.000000000000000000000000001
Run Code Online (Sandbox Code Playgroud)
)
正如所料,这产生:
1000000000000000000000.000000000000000000000000001
Run Code Online (Sandbox Code Playgroud)
同样如预期的那样,这不是在一条CPU指令中完成的.
我不得不反对Lutz ......虽然您提到的舍入错误确实存在于Python/Perl/Ruby中,但它们与C中实现的语言完全无关.问题比这更深入.
与所有数据一样,浮点数在现代计算机上以二进制表示.正如存在具有周期性十进制表示的数字(例如,1/3 = 0.333333 ......),也存在具有周期性二进制表示的数字(例如,1/10 = 0.0001100110011 ......).由于这些数字不能在(有限数量的)计算机存储器中准确表示,因此涉及它们的任何计算都将引入错误.
这可以通过使用高精度数学库来解决,这些数学库将数字表示为分数的两个数字(即"numerator = 1,denominator = 10")或字符串而不是使用本机二进制表示.但是,由于对作为其他内容存储的数字进行任何计算所涉及的额外工作,这些库必然会减慢必须通过它们的任何数学运算.
Python中有几种类型的非整数:
x = 1 / 2
Run Code Online (Sandbox Code Playgroud)
会给你标准浮动.它的类型是float,它与C中的基本相同,它由硬件处理,并且它具有与float世界上其他所有相同的问题.
但是,也有小数类型:
from fractions import Fraction
x = Fraction(1, 2)
Run Code Online (Sandbox Code Playgroud)
它具有合理数字的精确算术.
如果您想要进行舍入,但不满意计算机上有意义数字的数量,或者它可能在不同平台上有所不同,则十进制类型是您的朋友:
from decimal import Decimal
x = Decimal('0.5')
Run Code Online (Sandbox Code Playgroud)
如果您愿意,您可以将其精度设置为100位数.或者将银行应用程序设置为2.
只要计算机是愚蠢的,我们可能需要这么多不同的类型.至少,根据Pythonic原则,Python要求您明确选择您想要的数字.
而且,一个很大的误解是,精确的算术不会导致舍入问题.任何时候你用精确的值来为用户做一些有用的事情 - 例如将它打印给用户或者将多少美元添加到用户的银行账户---你会遇到舍入的"奇怪行为".这是非整数算术所固有的.