Scilab中浮点计算的精度是多少?

Posted

技术标签:

【中文标题】Scilab中浮点计算的精度是多少?【英文标题】:What is the precision of floating point calculations in Scilab? 【发布时间】:2016-06-07 18:33:37 【问题描述】:

注意:我使用了 Matlab 标签,以防它们保持相同的精度。 (据我所知,这两个程序非常相似。)

作为我上一个问题 (here) 的后续行动,我正在尝试确定我需要设置的精度级别(在我目前从 Scilab 代码转换的 C++ 程序中)订购 mock Scilab 程序的准确性。本质上,这两个程序都产生了相同(或非常相似)的结果。

在 Scilab 中进行浮点计算时,保持的精度是多少?

我读过(here 和其他一些地方)在 C++ 中使用浮点算术时,双精度只能保持大约 16 位小数,例如:

     4   8  12  16
     v   v   v   v
0.947368421052631578 long double
0.947368421052631526 double

与 Scilab 相比,这种准确性有多相似?

【问题讨论】:

在“小数位”中评估浮点错误并不是真正有效的。 1.999999999999999999999999999 和 2.0 呢?这些在所有小数位上都不同。错误取决于整个数字而不仅仅是小数部分。 IEEE 754 双精度浮点数是大多数常用语言(如 MATLAB、C++ 和 SciLab)中的标准表示:google.com/… 所以我不认为您需要做任何特殊的事情来表示精度,而不是使用 C++ 双精度(除非您的 SciLab 代码使用高精度浮点数)。 不,它们不必相同。浮点标准只保证大约 16 位有效数字的准确性……除此之外,额外的数字实际上毫无意义。 值得一提的是,Scilab 是开源的,您可以浏览当前源代码here。简单看一下,我看到很多 C 和 C++ 代码使用 double 进行计算。因此,SciPy 的浮点类型很可能与相关平台上的 C 双精度完全匹配。 @PaulWarnick:答案最多为 16 位(因为 IEEE 标准要求双精度浮点数的精度级别) 【参考方案1】:

重新发布评论作为答案:

IEEE 754 双精度浮点数是大多数常用语言(如 MATLAB、C++ 和 SciLab)的标准表示:

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwiajY7LzZbNAhWJix4KHcrEA1wQFgggMAA&url=http%3A%2F%2Fforge.scilab.org%2Findex.php%2Fp%2Fdocscifloat%2Fdownloads%2Fget%2Ffloatingpoint_v0.2.pdf&usg=AFQjCNFQiOVdgkjuxhFXhp1PwDFY-J-Qbg&sig2=vH0cpadZqi0bNqa9F0Gmig&cad=rja

所以我认为您不需要做任何特殊的事情来表示精度,除了使用 C++ 双精度(除非您的 SciLab 代码使用高精度浮点数)。

请注意,两种不同的 IEEE 754 兼容实现的表示在 16 位有效数字之后可能会有所不同:

MATLAB:

>> fprintf('%1.30f\n',1/2342317.0)
0.000000426927695952341190000000

Python:

>> "%1.30f" % (1/2342317,)
'0.000000426927695952341193713560'

【讨论】:

你回答中的最后一点是什么让我着迷。这种语言是特定的吗?意思是,如果您使用相同的语言,每次运行计算时,特定计算的 16 位数字之后的数字是否相同?此外,如果在 16 位之后,数字可能会有所不同。我应该如何在保持相同结果的同时将程序从一种语言 (Scilab) 转换为另一种 (C++)?有什么方法可以截断数字以便只使用前 16 位数字(因此计算相同)? 不是特定于语言,而是特定于平台/语言,是的。因此,如果我在 Windows 上的 MATLAB 2015b 中运行上述语句,我每次都会得到相同的“额外数字”。但是,如果我在 Linux 上切换到 MATLAB,甚至是不同版本的 MATLAB,我不能保证这些相同的“额外数字”。 但重点是,您为什么担心“多余的数字”?它们不是真实的。如果您有一个实际使用超过 16 个有效数字的应用程序(对于现实世界的问题,这些数字非常罕见),那么您需要使用大多数常用语言作为扩展的高精度数学库之一。但是,仅仅尝试将任意数字从一个实现匹配到另一个实现是毫无意义的。 谢谢,现在这更有意义了。我想我的想法是 Scilab 保持比 C++ 双精度更高的精度。而实际上它是相同的(16 位数字)。【参考方案2】:

每种通用语言(标准 C++、scilab、matlab 等)都使用相同的格式来表示十进制数。它在 IEEE754 上广为人知,其精确文档解释如下:

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

这意味着几乎所有常用系统的精度都保持不变。这是一个接近 2^-52(或等效于 2.2204e-16)的数字。它定义了“从 1.0 到下一个最大双精度数的距离”。

使用scilab时,可以通过%eps命令https://help.scilab.org/docs/5.5.1/fr_FR/percenteps.html进行确认。对于 matlab,它存储在 eps 变量 http://nl.mathworks.com/help/matlab/ref/eps.html 中。对于 C++,它有点难(参见:http://en.cppreference.com/w/cpp/types/numeric_limits/epsilon)。

因此,如果您不使用特定机器(非典型架构或非常非常旧的计算机或高精度小数(64 位双精度)),请不要担心精度。默认值将始终遵循相同的标准 (IEEE 754)。

但是,不要忘记,即使它看起来是一个常数,在非常大的数字和非常小的数字之间,误差可能是不一样的(系统被设计为在区间 [0, 1 [ 并且对于区间 [1, MAXIMUM[)。

如下例所示:

>>> 1e100 == 1e100+1
True
>>> 1 == 2
False

为确保您的代码可移植到不同的语言,我建议您明确引用提供机器精度的函数。例如,在 scipy 中:print(np.finfo(float).eps)。但是,一般来说,精心设计的算法在具有稍微不同的 epsilon 的机器上不会有太大的不同。

例如,如果我为趋向于 0(渐近)的东西实现循环,在 matlab 中,我应该写:

while(val < eps) do
...
end

因此,主要建议应该是:不要构建会尝试使用来自机器的过多信息的算法。要么您可以使用 epsilon 的实际值,要么您可以硬编码 2e-15 之类的东西。它可以在很多不同的机器上工作。

【讨论】:

这是一个很好的答案,但不幸的是,接受的答案澄清了我想知道的一切。 没问题 :) 我会保留它以便为进一步阅读提供额外信息^^ “使用相同的格式来表示十进制数”:实际上它们是二进制的,而不是十进制的。 我不是以英语为母语的人,但我想使用小数来定义一个带有小数部分(即在点之后)的数字,以便与整数进行对比。也许我应该使用“双数”,但它更多来自“计算机科学”而不是“通用语言”。我错了吗?

以上是关于Scilab中浮点计算的精度是多少?的主要内容,如果未能解决你的问题,请参考以下文章

请问浮点型数据在计算机是怎么存储的

浮点型是啥意思

解决浮点型数值计算精度丢失的一种实现

js 浮点小数计算精度问题 parseFloat 精度问题

用于提高中间浮点计算精度的编译器标志

Js浮点运算存在精度问题