如何在SQL Server中获取准确的值

时间:2017-08-07 17:36:14

标签: sql sql-server

我将100000 = Amount分为9 = Shift to Days = 30

但是当我需要实际数量时,我该怎么做呢?

在SQL中:

GNU C Library (Ubuntu GLIBC 2.23-0ubuntu9) stable release version 2.23, by Roland McGrath et al.

我需要100,000,但结果是99900.00 - 为什么?

2 个答案:

答案 0 :(得分:2)

默认情况下,sql会进行整数除法。只需添加*1.0即可进行十进制除法

Set @R1=100000*1.0/9/30

<强> SQL DEMO

使用float而不是money

SELECT (100000/9/30)*9*30 result, 'v1' as version
UNION 
SELECT (100000*1.0/9/30)*9*30,  'v2'
UNION 
SELECT (CAST(100000 as float)/9/30)*9*30, 'v3'
ORDER BY version

<强>输出

enter image description here

答案 1 :(得分:0)

欢迎来到漂浮点舍入错误的精彩世界。 100000 / 9 = 11111.1111...重复。让我们简化示例并假装我们只想要10 / 3;功能不同,问题相同。当10 / 3表示为分数时,您可以执行(10 / 3) * 3,取消三分,然后返回10.但是,计算机将10 / 3存储为3.33333...重复,输出尽可能高的精度。这种精确度实际上是一个有点复杂的问题,但它足以说明,它不是无限的。所以实际存储的内容类似于3.333333....0。当你乘以3时,计算机说&#34;啊,你让我乘以3.3333 ... 0 * 3,当然是9.99999 ... 0&#34;。

在数学上,你期望得到10回(或者在你的情况下,100,000)是完全合理的。但是由于计算机如何存储具有重复小数的数字,计算机无法识别10 / 33.33333...之间的等价性(实际上,它有点,但原因是它的确可能更多地与运气有关;稍后会详细介绍。

正如在另一个答案中指出的那样,你获得99900的原因是因为它进行整数除法而不是浮点除法。那么问题就变成你为了得到你想要的答案而投出100000了吗?

在你的情况下,float似乎是正确的,尽管值得注意的是,并非所有情况都是如此。这可能是正确的,因为float在其尾数(有效数字)中有53个小数位,并且具有该精度级别,SQL做出了有根据的猜测,事实上,您试图重新形成具有无限重复小数位的分数而不是将三个数字相乘,但不等于原始数字。

另一方面,

Money作为数据类型通常是一个糟糕的选择,因为它实际上只是一个小精度float并导致这样的问题。 Decimal在这种情况下也存在一些问题,因为它实际上超调重新形成的值。

declare 
    @Money money = cast(100000 as money) / 2700, 
    @Float float = cast(100000 as float) / 2700, 
    @Decimal decimal(38,2) = cast(100000 as decimal(38, 2)) / 2700

select 
    _Money = @Money,
    _MoneyReformed = @Money * 2700,
    _Float = @Float,
    _FloatReformed = @Float * 2700,
    _Decimal = @Decimal,
    _DecimalReformed = @Decimal * 2700

如果你需要一个真实的,普遍正确的分数表示,你必须将分子和分母存储在不同的列中,这样你就可以独立地操作每个分子和分母。