我想生成一个float数组。例如,这一个:
[0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
所以,我使用这条小线:
(0.5..2).step(0.1).to_a
但它产生了这个:
[0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2000000000000002, 1.3, 1.4, 1.5, 1.6, 1.7000000000000002, 1.8, 1.9000000000000001, 2.0]
我做错了什么?
答案 0 :(得分:6)
无法精确表示0.1
等浮点数。使用浮动指针数作为步骤会给你意想不到的结果。
更好的选择是:
(5 .. 20).map {|e| e / 10.0}
#=> [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
答案 1 :(得分:3)
浮点数可以咬你。具体而言,binary can't represent 0.1 accurately。 Ruby有许多类可以准确处理任意精度的数字,包括BigDecimal和Rational。
您可以使用新的2.1 syntax for rational literals来创建一系列花车。例如:
(0.5r..2r).step(0.1r).map &:to_f
#=> [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
这样做可能看起来比currently-accepted answer更混乱,但这种方法适用于更广泛的精度问题,其中除以10.0不是解决方案。
答案 2 :(得分:1)
我会像@YuHao建议的那样做 - 干净且易于阅读 - 但我想指出你也可以使用BigDecimal类:
require 'bigdecimal'
v = BigDecimal.new(0.5, 1)
a = (20-5+1).times.with_object([]) { |_,arr| arr << v.to_f; v += 0.1 }
#=> [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2,
# 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
注意:
BigDecimal
初始化Float
对象时,必须给出精度(此处为, 1
)。v
是BigDecimal
的实例,v + 0.1
也是如此。BigDecimal
没有succ
方法,因此无法进行迭代。因此,不能只将BigDecimal
范围映射到Floats
数组中。 (BD
的范围是允许的,但我质疑无法迭代的范围的效用。)答案 3 :(得分:0)
另一个问题,如何获得此结果(保留2位小数)
[0.50,0.60,0.70,0.80,0.90,1.00,1.10,1.20,1.30,1.40,1.50,1.60,1.70,1.80,1.90,2.00]