SQLite - 浮点数/小数的总和导致错误的总和

时间:2015-10-16 11:12:16

标签: sqlite

我试图获取包含十进制数的列的总和。结果真的很奇怪。

我尝试使用float和decimal数据类型。

以下列具有以下数据类型:

"euro_out" float
"makes" decimal(10,9)

一些查询和结果:

1。)当值为整数

时的预期结果
sqlite> update bookingviews set makes = 1.0;
sqlite> select total(makes) from bookingviews;
==> 1728212.0

2。)值具有十进制值时的意外值:

sqlite> update bookingviews set makes = 0.1;
sqlite> update bookingviews set euro_out = 0.1;
sqlite> select total(makes) from bookingviews;
==> 172821.200005572
sqlite> select total(euro_out) from bookingviews;
==> 172821.200005572

正确的结果应该是172821.2,因为有1728212行,其值为0.1。

为什么额外0.000005572?我该如何纠正这种行为?

谢谢。

2 个答案:

答案 0 :(得分:0)

对于64位类型,浮点运算仅精确到约15个有效数字,对于32位类型,浮点运算仅为7个有效数字。

因此,它们并非旨在用于代表金钱。

一个简单的选择是使用64位整数,并报告" cents&#34 ;;也许美容上呈现在"美元"如果合适的话。

答案 1 :(得分:0)

我偶然发现了同样的问题。这是一个更完整的示例,可重现:

create table test (value decimal(16, 6) not null);
insert into test values (13.709465), (8.606133), (3.961969), (3.5028), (2.886203), (1.298791), (0.695313), (0.629717), (0.380453), (0.28862), (0.275501), (0.262382), (0.236142), (0.170548), (0.170547), (0.157429), (0.144309), (0.13119), (0.065595), (0.065595), (0.065595), (0.065595), (0.065595), (0.065595), (0.052476), (0.052476), (0.052476), (0.039357), (0.039357), (0.039357), (0.026238), (0.026238), (0.026238), (0.026238), (0.026238), (0.026238), (0.026238), (0.026238), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119), (0.013119);
select sum(value) from test;

它输出:

38.5701510000001

这很容易被认为是错误的,因为将小数点后不超过六位数的数字相加,结果中的小数点后不能超过六位数。

阅读the documentation揭示了原因:

如果sum()的任何输入都不是整数或NULL,则sum()返回一个浮点值,该值可能是真实总和的近似值。

使用decimal作为类型当然可以避免此类问题,但是sum实在不愿意使用IEEE-Floats。

可能的解决方法是改用整数。您需要先将小数转换为整数,然后求和,然后再转换回。在我的示例中,我有一个decimal(16, 6),因此我需要乘以1e6以获得一个干净的整数:

sqlite> select sum(cast(value * 1e6 as integer)) / 1e6 from test;
38.570151

您有一个decimal(10,9),因此需要改用1e9。

请注意,SQLite最多使用8个字节表示一个整数,因此最大值为2 ^ 64,大约为1.8e19。就您而言,这意味着您可以使用的数据库最大数量为〜1.8e10。