Julia 为什么不能使用范围数组正确迭代这些值?
我遇到了这个问题Julia 为什么不能使用范围数组正确迭代这些值?,julia,Julia,我遇到了这个问题 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
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
出于某种奇怪的原因,我无法获得大于
0.15
的值。您在浮点运算中遇到了一个经典问题:
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
所以您的第一个问题是0.1+0.5==0.150000000000002>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
什么?!?为什么?发生这种情况是因为您的起点比您预期的要大(您的终点也比您预期的要大,但并不显著:0.2==2.000000000000000 111022302462565404236316680908203125
)。特别要注意的是
julia> (0.2-0.15000000000000002)/0.05
0.9999999999999998
换句话说,您正在构建的范围不够大,无法包含两个点。然而,情况也是如此:
julia> 0.15000000000000002 + 0.05
0.2
可以论证的是,如果您可以添加步骤n
次数并准确地到达终点,那么范围应该包括该终点,因此这可能被视为一个bug(问题字段:)。但是,我相当肯定,我们可以找到其他情况,在这些情况下,您的算法将积累足够的浮点错误而导致失败
有几种可能的解决方案:
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
正如您所看到的,这并没有完全解决浮点错误问题,但是错误不会在一次迭代到下一次迭代中累积
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
如您所见,这实际上完全消除了不精确问题