小数点后 19 位及以上的数学精度

Mathematical precision at 19th decimal place and beyond

我有相同的数据集并且是 运行 相同的代码,但有时我会在小数点后 19 位及以后得到不同的结果。虽然对于小于 0.0001 的数字我不是很关心,但这让我想知道小数点后第 19 位是否是 Raku 的精度极限?

     Word 104 differ: 
             0.04948872986571077     19 chars 
             0.04948872986571079     19 chars
     Word 105 differ: 
             0.004052062278212545    20 chars 
             0.0040520622782125445   21 chars

TL;DR 请参阅文档的未完成 Numerics 页。


(在我写下面的答案之前我已经忘记了那个页面。考虑这个答案最多是那个页面的几个方面的简短总结。)


这有两个方面。内部精度和印刷精度。

100% 内部 精度直到 RAM 耗尽

Raku 支持任意精度数字类型。引用 Wikipedia's relevant page:

digits of precision are limited only by the available memory of the host system

您可以指示 Raku 使用其中一种任意精度类型。[1] 如果您这样做,它将保留 100%精度,直到它 运行s 超出 RAM。

Arbitrary precision type Corresponding type checking[2] Example of value of that type
Int my Int $foo ... 66174449004242214902112876935633591964790957800362273
FatRat my FatRat $foo ... 66174449004242214902112876935633591964790957800362273 / 13234889800848443102075932929798260216894990083844716

因此你可以获得整数和分数的任意内部精度(包括任意精度小数)。

有限内部精度

如果您不指示 Raku 使用任意精度数字类型,它会尽力而为,但最终可能会切换到有限精度。例如,如果您使用的公式计算 Rat 并且数字的分母超过 64 位,Raku 将放弃 100% 的精度。[1]

Raku 的回退有限精度数字类型是 Num:

On most platforms, [a Num is] an IEEE 754 64-bit floating point numbers, aka "double precision".

引用 the Wikipedia page for that standard:

Floating point is used ... when a wider range is needed ... even if at the cost of precision.

The 53-bit significand precision gives from 15 to 17 significant decimal digits precision (2−53 ≈ 1.11 × 10−16).

打印精度

与内部精度不同的是数字的字符串化。

(正是在这个阶段,我想起了这个答案开头链接的关于数值的文档页面。)

引用 Printing rationals:

Keep in mind that output routines like say or put ... may choose to display a Num as an Int or a Rat number. For a more definitive string to output, use the raku method or [for a rational number] .nude

脚注

[1] 您可以通过表达式中各个数字的类型以及数字运算的结果,这又取决于数字的类型。示例:

  • 1 + 23,一个Int,因为12都是Int,并且 a + b 是一个 Int 如果 ab 都是 Ints;

  • 1 / 2 而不是 一个 Int 即使 12 都是单独的 Ints,而是 1/2 又名 0.5,一个 Rat.

  • 1 + 4 / 2 打印出 作为 3,但 3 在内部是一个 Rat,不是 Int,因为 Numeric infectiousness

[2] 如果您尝试分配或绑定,强制执行的所有操作都会产生 运行 时间错误不是您指定为变量类型约束的数字类型的值。强制执行并不意味着 Raku 会为您转换号码。您必须编写公式以确保得到的结果是您想要的。[1]可以 使用强制转换——但强制转换无法恢复已经丢失的精度。