Postgresql 中浮点型和数字型有什么区别?

tur*_*tle 5 postgresql database-design floating-point

阅读有关数字数据类型的Postgresql 文档 让我想到了这个问题:为什么在 Postgresql 中使用数据类型Float(SQL 标准)会得到这些意外的结果Numeric

例如:

CREATE TEMP TABLE testnum (a numeric, b float);
INSERT INTO testnum VALUES (100,100);
INSERT INTO testnum VALUES (9*9*9,9*9*9);
INSERT INTO testnum VALUES (9^9^9,9^9^9);
SELECT (a/3)*3 AS numeric, (b/3) * 3 AS float FROM testnum;
SELECT (a/5)*5 AS numeric, (b/5) * 5 AS float FROM testnum;
Run Code Online (Sandbox Code Playgroud)

然后运行

SELECT (a/3)*3 AS numeric, (b/3) * 3 AS float FROM testnum;

numeric                                     |         float          
                        99.9999999999999999 |                    100
                       729.0000000000000000 |                    729
Run Code Online (Sandbox Code Playgroud)

在这个测试中Float看起来比 更准确Numeric

哪一种数据类型适合精确数值(例如货币或库存数量)?

mus*_*cio 5

您正在成为隐式类型转换的受害者。当其中一个操作数为numeric且另一个integer操作数为 时,将转换为整数操作数numeric,结果为numeric。由于numeric具有严格定义的精度,因此尝试为其分配小数点后无限多位的值(100/3 产生的值)而不进行四舍五入,将导致截断。同样的逻辑也适用于乘法,其中一个操作数现在不是所期望的 33.333...(具有无限的“3”序列),而是定义的精度numeric33.333...3(有限的“3”序列) “3”),自然产生 99.999...9——有限序列

当其中一个操作数为float且另一个integer操作数为 时,将转换为整数操作数float,结果为float。由于float具有近似精度,因此它可以以不同的方式处理 33.333... 和 99.999...,最终得到近似值 100。

至于

哪一种数据类型适合精确数值(例如货币或库存数量)?

该手册为您提供了所需的确切答案:

如果您需要精确的存储和计算(例如货币金额),请改用数字类型。

没有说的是,您应该通过使用适合您的业务规则的显式类型转换和舍入来控制每个步骤的计算。