我将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 - 为什么?
答案 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
<强>输出强>
答案 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 / 3
和3.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
如果你需要一个真实的,普遍正确的分数表示,你必须将分子和分母存储在不同的列中,这样你就可以独立地操作每个分子和分母。