Julia 和 Matlab 之间的模数语句结果不同——在 Julia 中使用浮点数时避免舍入错误的最佳实践?

Modulus statement result differ between Julia and Matlab – best practice for avoiding rounding errors when working with floats in Julia?

我正在编写一个 Julia 程序,其中有一个需要满足以下条件的 Float64 变量 (val):

(val – m) % s == 0

ms 是存储为字符串的数字,例如:m = "0.00010000"s = "0.00010000".

如果我在 Matlab 中进行如下计算:

val = 0.2383;
m = "0.00010000";
s = "0.00010000";
result = mod((val - str2double(m)), str2double(s)) == 0;
disp( result )

答案被评估为正确。即满足 (val – m) % s == 0 标准。

但是,当我尝试在同一程序的 Julia 实现中做同样的事情时,我 运行 遇到了问题:

val = 0.2383;
m = "0.00010000";
s = "0.00010000";
result = ((val - parse( Float64, m )) % parse( Float64, s )) == 0;
println( result ) 

相同计算的 Julia 版本现在变为错误。

这可能是由于浮点数舍入错误,Julia 中 val – parse(Float64, m) 的结果例如是 0.23820000000000002,它不能被 0.0001 整除。

所以我的问题是:在 Julia 中,我如何调整我的计算,以便像在 Matlab 代码中那样满足标准?我可以用不同的方式解析我的 val/m/s 变量以避免舍入问题吗?

理想情况下,出于速度考虑,我想避免使用“Decimals”等包并坚持使用快速变量类型。

这不是语言问题,而是您的 CPU 如何处理浮点运算。以 10 为基础的系统中的数字是有理数,但在二进制系统中却不是有理数。

也许 Matlab 提供了一些执行舍入而不告诉用户的实现。但舍入总是另一个单独的操作。

在 Julia 中你可以这样做:

julia> isapprox( ((val - parse( Float64, m )) % parse( Float64, s )), 0, atol=eps())
true

请注意,还有一个运算符 ,但对于您的示例,它的默认容差似乎缩小了。尝试在 Julia 控制台中输入 ?≈ 以获取更多详细信息。

Przemyslaw Szufel 的回答可能是最通用和最正确的答案。然而,我最终用来解决这个问题的是 DecFP.jl 包(对于将来遇到类似问题的人来说可能是件好事)。将数字解析为 Dec64 固定精度时,舍入错误已解决。 Dec64 不如常规 Float64 快,但它仍然比使用 Decimals.jl.

更有效