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
m
和 s
是存储为字符串的数字,例如: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.
更有效
我正在编写一个 Julia 程序,其中有一个需要满足以下条件的 Float64 变量 (val
):
(val – m) % s == 0
m
和 s
是存储为字符串的数字,例如: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.
更有效