Ruby / Big Decimal - 无法执行保存

时间:2014-10-27 09:10:42

标签: ruby-on-rails ruby sql-server

我有一个需要保存18位数值的列。它在我的rails文件中定义为

Schema.rb

 t.decimal  "revenue",    precision: 23, scale: 5

现在,当我在控制台中尝试以下操作时:

obj = Model.last
obj.revenue = 999999999999999999 ( 18 nines)
obj.save is returning false 

(我已确认最大收入应小于1000000000000000000(1后跟18个零)

对模态的验证:

validates :revenue , numericality: {:greater_than => WBConstants::MIN_REVENUE_LIMIT, :less_than => WBConstants::MAX_REVENUE_LIMIT}, allow_blank: true

错误消息显示该值应小于100 ...(1后跟18个零)

我无法保存。 我使用的数据库是sqlserver 列数据类型为decmial(23,5)

2 个答案:

答案 0 :(得分:2)

这是Rails中的一个错误,已经有pull request

在修复合并之前,您可以perform custom validation

造成此错误的原因是什么?

使用Kernel.Float

在内部converts the value内部导航到浮点数
f = Kernel.Float(999_999_999_999_999_999)
#=> 1.0e+18

f < 1_000_000_000_000_000_000
#=> false

f == 1_000_000_000_000_000_000
#=> true

为什么会这样?

因为浮点数的精度有限,并且只能完全代表某些整数:

(999999999999999000..1000000000000001000).map { |i| i.to_f.to_i }.uniq
#=> [999999999999998976,
#    999999999999999104,
#    999999999999999232,
#    999999999999999360,
#    999999999999999488,
#    999999999999999616,
#    999999999999999744,
#    999999999999999872,
#   1000000000000000000,
#   1000000000000000128,
#   1000000000000000256,
#   1000000000000000384,
#   1000000000000000512,
#   1000000000000000640,
#   1000000000000000768,
#   1000000000000000896,
#   1000000000000001024]

有关详细信息,请参阅What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 1 :(得分:0)

到目前为止,您可以使用自定义验证来解决此问题。 请查看以下链接: Custom Validators

希望这对你有所帮助。