我遇到了这个问题
julia> Tinit = 0.0
0.0
julia> for ii in 1:10
timeinterval = Tinit:0.05:(Tinit + 0.05)
println(Tinit + 0.05)
for item in timeinterval
println("+++++++++ ", item)
end
Tinit = timeinterval[end]
end
Run Code Online (Sandbox Code Playgroud)
而且由于一些奇怪的原因,我无法获得超过的价值 0.15
Ste*_*ski 11
您在浮点运算中遇到了一个经典问题:
julia> 0.05 + 0.05
0.1
julia> 0.05 + 0.05 + 0.05
0.15000000000000002
julia> 0.05 + 0.05 + 0.05 + 0.05
0.2
Run Code Online (Sandbox Code Playgroud)
所以你的第一个问题是0.1 + 0.5 == 0.15000000000000002 > 0.15.请参阅浮点数学是否已损坏?.所以你没有得到你希望得到的确切实数.你遇到的第二个问题是你正在构建一个范围:
julia> r = 0.15000000000000002:0.05:0.2
0.15000000000000002:0.05:0.15000000000000002
julia> length(r)
1
julia> r[end]
0.15000000000000002
Run Code Online (Sandbox Code Playgroud)
什么?!?为什么?这是因为你的起点比你预期的要大(你的终点也比你预期的要大,但不是很明显:) 0.2 == 2.00000000000000011102230246251565404236316680908203125.特别要注意的是
julia> (0.2-0.15000000000000002)/0.05
0.9999999999999998
Run Code Online (Sandbox Code Playgroud)
换句话说,你正在构建的范围不够大,不能有两个点.但是,情况也是如此:
julia> 0.15000000000000002 + 0.05
0.2
Run Code Online (Sandbox Code Playgroud)
可以说,如果你可以添加步骤n时间并准确地命中终点,那么范围应该包括那个终点,所以这可以被认为是一个错误(问题提交:#20373).但是,我相当确定,我们可以找到其他情况,您的算法会积累足够的浮点错误.
有几种可能的解决方案:
1)不要进行绝对浮点计算而不是迭代浮点计算.例如,您可以将您的范围表示为(0:0.05:0.05) + Tinit + (ii-1)*0.05:
julia> Tinit = 0.0; for ii in 1:10
println(Tinit + (ii-1)*0.05 + (0:0.05:0.05))
end
0.0:0.05:0.05
0.05:0.05:0.1
0.1:0.05:0.15
0.15000000000000002:0.05:0.2
0.2:0.05:0.25
0.25:0.05:0.3
0.30000000000000004:0.05:0.35000000000000003
0.35000000000000003:0.05:0.4
0.4:0.05:0.45
0.45:0.05:0.5
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这并不能完全解决浮点错误问题,但错误不会从一次迭代累积到下一次迭代.
2)使用精确的整数运算,除以100或任何除数,将该计算降低到最接近的可表示浮点值.由于浮点只用于表示,而不是核心计算,因此核心计算是正确的并且永远不会累积错误.
julia> Tinit = 0.0; for ii in 1:10
println((Tinit+(ii-1)*5)/100:0.5:(Tinit+ii*5)/100)
end
0.0:0.5:0.0
0.05:0.5:0.05
0.1:0.5:0.1
0.15:0.5:0.15
0.2:0.5:0.2
0.25:0.5:0.25
0.3:0.5:0.3
0.35:0.5:0.35
0.4:0.5:0.4
0.45:0.5:0.45
Run Code Online (Sandbox Code Playgroud)
如您所见,这实际上完全消除了不精确的问题.