SQL Server十进制计算错误

时间:2017-05-23 06:35:29

标签: sql-server decimal

我知道这不是典型的问题,抱歉。

最近我在Microsoft SQL Server中遇到了一件奇怪的事情。似乎将小数(30,10)计算舍入到小数点后的第六位。展示它非常简单:

select 0.0000009 * 1;
-- 0.0000009, perfect
select cast(0.0000009 as real) * cast(1 as real);
-- 9E-07, that's also 0.0000009, sehr gut!
select cast(0.0000009 as decimal(18,10)) * cast(1 as decimal(18,10));
-- same number – no surprise
-- but:
select cast(0.0000009 as decimal(30,10)) * cast(1 as decimal(30,10));
-- yields 0.000001!

但是让我继续前进:

select cast(0.0000008 as decimal(30,10)) * cast(1 as decimal(30,10));
-- 0.000001, same thing
select cast(0.0000007 as decimal(30,10)) * cast(1 as decimal(30,10));
-- 0.000001, same thing    
select cast(0.0000005 as decimal(30,10)) * cast(1 as decimal(30,10));
-- 0.000001, same thing
--     
select cast(0.0000004999 as decimal(30,10)) * cast(1 as decimal(30,10));
-- 0.000000! why the hell is it rounding!?
-- and the crown jewel:
select cast(0.00000049999 as decimal(30,10)) * cast(1 as decimal(30,10));
-- 0.000001, rounded up to get the same thing as above, insane!

起初我认为这是一个简单的计算或十进制与二进制表示错误,所以我开始挖掘实际记录并看到那里的十六进制内存转储(full story here)。但当然它没有帮助,我意识到当我尝试上面的第二个代码块时得出的结论是在这个过程的某个地方有一个四舍五入的原因。

出于好奇 - 因为我已经向微软报告了 - 你会做什么,如何继续调查这个错误?我想知道后台正在进行哪些操作。

0 个答案:

没有答案