use*_*471 4 ruby sqlite floating-point ruby-on-rails bigdecimal
我正在玩铁轨,我发现了一些奇怪的东西.为了存储货币值,我使用典型的十进制数据类型,活动记录转换为BigDecimal.我认为这是精确的,我想避免浮点数学的奇怪行为.但是当我将99.99存储到数据库时,一切正常,但是当记录被活动记录加载时,它会失去精度并转换为99.9899999999之类的东西.这看起来像一个浮点问题.
我做了一些测试,发现像这样创建一个BigDecimal b = BigDecimal.new("99.99")导致一个"干净"的变量但是这样构建它b = BigDecimal.new(99.99)会导致"不洁"的版本我想避免.
我想,当从数据库加载记录时,ActiveRecord用一个中间浮点重建BigDecimal.这不是我想要的,我想知道是否可以避免.
Ruby版本1.9.3p0 Rails 3.2.9 Sqlite 3.7.9
您的问题是您使用的是SQLite,而SQLite没有对numeric(m,n)
数据类型的本机支持.从精细手册:
1.0存储类和数据类型
存储在SQLite数据库中(或由数据库引擎操纵)的每个值都具有以下存储类之一:
- 空值.该值为NULL值.
- 整数.该值是有符号整数,存储为1,2,3,4,6或8个字节,具体取决于值的大小.
- 真实.该值是浮点值,存储为8字节IEEE浮点数.
- 文本.该值是一个文本字符串,使用数据库编码(UTF-8,UTF-16BE或UTF-16LE)存储.
- BLOB.该值是一个数据块,与输入完全一样.
请继续阅读该页面,了解SQLite的类型系统的工作原理.
您的99.99可能BigDecimal.new('99.99')
在您的Ruby代码中,但它几乎可以肯定是SQLite中的REAL值99.99
(即一个8字节的IEEE浮点值)并且存在邻域.
因此,在开发环境中切换到更好的数据库; 特别是,在您要部署的任何数据库之上进行开发.