我一直在对包含大约 500.000 条双精度数字记录的列进行总和。数据库中的所有数字通常应该在句点后面有两个密码。但是,在计算总和时,我得到了 6 个数字:123123123.549977
要么我的数据库中有错误的数据,在这段时间之后有更多数字的记录,要么我缺少 sum 函数的一些东西。
所以我的问题是:
- sum 函数是否有任何可能导致这种情况的舍入属性?
- 有没有办法在句号之后选择所有包含两个以上数字的记录?
我一直在对包含大约 500.000 条双精度数字记录的列进行总和。数据库中的所有数字通常应该在句点后面有两个密码。但是,在计算总和时,我得到了 6 个数字:123123123.549977
要么我的数据库中有错误的数据,在这段时间之后有更多数字的记录,要么我缺少 sum 函数的一些东西。
所以我的问题是:
这是浮点数无处不在的常见问题。
存储在计算机系统中的浮点数只应被视为近似值,因为当转换为二进制时,有些数字很容易以十进制表示,但它们的输出长度超过了可用的精度(有时它们实际上是永无止境的)。有关更多详细信息,请参阅 ypercube 的链接和https://stackoverflow.com/questions/588004/is-floating-point-math-broken以及许多其他参考资料。
给出的最常见示例(如 StackOverflow 链接所示)是 0.1+0.2,而不是正好为 0.3。您必须应用额外的舍入或灵活的边界检查(在这两种情况下都会降低有效精度)才能获得您期望的行为。
由于您的数据在 2 处具有固定的小数位数(或固定的最大值),因此使用固定位数的小数/数字类型或类似类型会更好。这些实际上是作为缩放整数存储和处理的,避免了内部需要任何浮点表示,从而避免了近似问题(假设您有足够的数字/位,所有整数都可以在基数 10 和基数 2 中准确表示)。例如,0.1 和 0.2 可能存储为 1000 和 2000,因此相加结果为 3000,当转换为字符串以进行显示时,它变为 0.3 而不是 0.3000000004,您可能会从浮点计算中得到,当然与 3 in相同的类型将缩放到 3000。
您可以转换为字符串并计算小数点后的字符(或逗号,具体取决于您的系统本地)。在 TSQL 中,这将找到在以二进制浮点格式存储然后转换回十进制后以多于两位小数结束的值:
(您可能需要调整 postgres 的函数名称和相关语法)。
大卫的回答是正确的,除了代码,这在 PostgreSQL 中是无意义的。
您正在寻找 > 2 位小数。找到它的最简单方法是转换为
NUMERIC
(任意精度十进制浮点)并从原始值中减去舍入值。(这实际上是非常标准的 SQL,它应该适用于许多数据库,并调整数据类型 -
DECIMAL
、NUMBER
、DECFLOAT
、NUMERIC
等)。另一种选择是设置
extra_float_digits=1
处理浮点到字符串格式的浮点/十进制不精确的错误,然后进行简单的模式匹配:我尝试过的另一种解决方案是转换为精度
varchar
,然后再转换回DOUBLE
精度,如下例所示: