当range遇上Float64,精度影响了range长?!

range这个函数挺逗的,有一些奇怪的特性。
比如说Float64明明是可以给我们不少于8位精度的,但偏偏在range里面,Julia会很通人性的擅自做修改。
修改就罢了,关键还有时候改有时候不改,看心情。

最近在写一个算分形的代码.遇到一个很奇葩的问题。

(下附解决方案)

dl = 5e-6

for i = 1:20
    λ = (((i-1)/20*2)):(dl):(i/20*2-dl)
    println(length(λ))
end

这没啥神奇的,只是给(\lambda) 一个range的值罢了。
然而,
请找出一堆20000里面隐藏的19999。。。

julia>

20000
20000
20000
20000
20000
20000
19999
20000
20000
20000
20000
20000
20000
19999
20000
20000
20000
20000
19999
20000

7 14 和 19真是神奇的数字。。。

让我们做一点修改(把除以20再乘以10改成乘.1)

dl = 5e-6

for i = 1:20
    λ = (((i-1)*.1)):(dl):(i*.1-dl)
    println(length(λ))
end

结果又是很神奇有没有。。。


20000
20000
20000
20000
20000
20000
19999
19999
20000
20000
20000
20000
19999
20000
19999
20000
20000
19999
20000
19999

看,和刚才不一样呢?!再改

for i = .1:.1:2
    λ = Float64(i-.1):Float64(dl):Float64(Float64(i)-Float64(dl))
    println(length(λ))
end
20000
20000
20000
20000
20000
20000
19999
19999
20000
20000
20000
20000
20000
20000
20000
20000
20000
20000
20000
20000

解决方案

range ()是可以设长度的!!!这避免了 数值计算的误差影响数据结构本身

i=7
λ = range((i-1)/20*2,Float64(i/20*2-dl),length = 20000)
length(λ)
λ[1]
λ[end]
λ[end-1]

7

0.6:4.999999999999997e-6:0.6999949999999999

20000

0.600

0.6999949999999999

0.6999899999999999

我的版本:

Starting Julia...
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
               _   _       _ _(_)_     |  Documentation: https://d
ocs.julialang.org
  (_)     | (_) (_)    |   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.1.0 (2019-01-21)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> 

努力摸索两小时,这样你就能省掉读文档五分钟的宝贵时间。。。

2 个赞

这跟range有什么关系?这是浮点运算的问题,python也是这样。
0.7 - dl = 0.6999949999999999 < 0.699995
0.8 - dl = 0. 79995
所以才会出现上述的情况,
建议碰到浮点数的时候要给一定的tol,没那么准确,恰好相等。

浮点数本身就是不准确的,不能直接判断等号和长度。这是IEEE标准,用什么函数前不确定可以看一眼文档。

摸索两小时,胜读文档五分钟。:smile:

事实上,我开始没打算用双精度,而是打算用 BigFloat(),
然而range() 不允许用“任意精度”浮点数。

然而我确实需要一个“任意精度”的range,(并不想写while loop)。
于是出现了奇葩解决方案

不能给tolerance,要用任意精度:rofl:
不过这样的话改成纯符号大数计算岂不是更。。。