表:
var1 | var2
-----+------
0.5 | 19.99
var1和var2是双精度类型
我知道,保存的值可能是19.9900000000000000000000000001或19.989999999999999999999999999999999(或0.5不准确),但是如何获得正确的值(如果小数部分正好是0.5,正数向上舍入,负数向下舍入。 - 来自round definition):
SELECT var1, var2, round(var1*var2,2), round(0.5*19.99,2), round(9.995,2) FROM table
返回
var1 | var2 | this should be 10 | this is 10 | this is also 10
| | round(var1*var2,2)| round(0.5*19.99,2) | round(9.995,2)
-----+-------+-------------------+--------------------+-----------------
0.5 | 19.99 | 9.99 | 10 | 10
我试过回合(圆(var1,2)*圆(var2,2))但没有改变
答案 0 :(得分:2)
0.5
和19.99
等文字分别为NUMERIC(18, 1)
和NUMERIC(18, 2)
。文字0.5 * 19.99
是NUMERIC(18, 3)
,这意味着结果值正好是9.995,当舍入到2位小时将导致NUMERIC(18, 3)
值为10.000。
另一方面,对双精度值的相同操作并不精确。例如:
select
val1 * val2,
cast(val1 * val2 as varchar(100)),
round(val1 * val2, 2),
round(val1 * val2, 3),
round(round(val1 * val2, 3), 2),
round(val1 * val2 + 1e-10, 2)
from (
select
cast(0.5 as double precision) as val1,
cast(19.99 as double precision) as val2
from rdb$database) a
将分别产生(在flamerobin中):
9.995000 9.994999999999999 9.990000 9.995000 10.000000 10.000000
第一列为9.995000是由flamerobin渲染的结果,最多6位小数(如第二列所示)。
这也可能暗示一个解决方案:首先轮到更高的小数位数,然后降低,或者添加一个小的分数,如1e-10
,但这仍然会产生与其他值不正确的舍入。
将结果转换为定点小数也是如此:您可能会在某处引入舍入错误。
答案 1 :(得分:0)
现在的解决方案:
SELECT ROUND(CAST(var1 AS DECIMAL(9,2))*CAST(var2 AS DECIMAL(9,2)),2) FROM table
但也许有人有更好的解决方案