如何在firebird中舍入乘法

问题描述 投票:0回答:3

表:

var1 | var2
-----+------
 0.5 | 19.99

var1 和 var2 是双精度类型

我知道,保存的值可能是 19.9900000000000000000000000001 或 19.989999999999999999999999999999999 (或 0.5 不准确),但如何获得正确的值(如果小数部分恰好是 0.5,则正数向上舍入,向下舍入)对于负数。-其中来自轮定义):

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

我尝试了 round(round(var1,2)*round(var2,2)) 但没有任何改变

rounding firebird
3个回答
3
投票

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

将分别产生(以火罗宾):

9.995000    9.994999999999999   9.990000    9.995000    10.000000   10.000000

第一列 9.995000 是由 Flamerobin 渲染的结果,最多保留 6 位小数(如第二列所示)。

这也可能暗示了一个解决方案:首先四舍五入到更高的小数位数,然后更低,或者添加一个小分数,如

1e-10
,但这仍然可能会产生与其他值不正确的舍入。

将结果转换为定点小数也是如此:您可能会在某处引入舍入误差。


0
投票

目前的解决方案:

SELECT ROUND(CAST(var1 AS DECIMAL(9,2))*CAST(var2 AS DECIMAL(9,2)),2) FROM table

但也许有人有更好的解决方案


0
投票

我认为这是最好的解决方案

SELECT round(round(val1 * val2, 3), 2) FROM table

© www.soinside.com 2019 - 2024. All rights reserved.