不小心又中了decimal的埋伏——重新捋一下decimal的相关知识

不小心又中了decimal的埋伏——重新捋一下decimal的相关知识,第1张

概述大家都知道在程序语言和数据库中各种数字类型decimal,numeric,float,double,real……,有时候不小心就会出现问题,除了掌握基本的数据存储原理,还要仔细了解各个语言和产品里的细节差别,即便如此,一不小心还是有可能中了埋伏。 在SQLserver中Decimal可以用来存储整数,也可以用来存储小数,而且精度高,所以我常常用来保存像销售类的数据相关字段。 情景再现 某数据表结构 大家都知道在程序语言和数据库中各种数字类型decimal,numeric,float,double,real……,有时候不小心就会出现问题,除了掌握基本的数据存储原理,还要仔细了解各个语言和产品里的细节差别,即便如此,一不小心还是有可能中了埋伏。 在sqlserver中Decimal可以用来存储整数,也可以用来存储小数,而且精度高,所以我常常用来保存像销售类的数据相关字段。 情景再现 某数据表结构如下:
create table demo(ID bigint,amount decimal(18,5),--总金额quantity decimal(18,5)--数量)
在编写一个功能其中使用了一句
select convert(decimal(18,2),amount)/convert(decimal(18,quantity) from demo where quantity>0.00
问题解决和分析 执行过程中总是报“被零除的错误”,看看代码觉得没有什么问题,仔细看后才明白,原本想我要的结果只需要保留2位小数,所以执行转换后再行计算,还有一方面是quantity>0.00的判断和前面的转换不匹配造成的。尽管0.00001虽然大于0.01符合筛选条件
但转化后就变成0.00了,所以才会出现上面的错误。 sql 2005中decimal的能够存储的数字范围是- 10^38 +1 到 10^38 - 1(见参考1),用科学计数法看不直观它的威力(^-^),最大正数就是4个1亿相乘以后再乘以1万减1。这是非常大的数字了。 回到正题,那么我们定义的两个字段都是decimal(18,5),表示精度为18,小数为5位, 但是要注意的是ms sql 中位数就是10进制的位数,也就是说decimal(18,5)表示-9999999999999.99999到9999999999999.99999之间的数字。这样decimal(18,5)和decimal(18,2)就有较大差别了,可以认为它们是不同的数据类型(见参考2),在两种数据数据类型之间转换,自然就可能有所损失。 解决就简单了,直接改为计算后在转化就行了。
select convert(decimal(18,2)/(amount/quantity)) from demo where quantity>0.00000
反思 其实解决以上问题很简单。之所以“小题大做”,主要还是觉得对数据类型掌握还不够细,总是觉得那么数据类型,大概对就行了,差不多就行,实际上这是不对的。 延伸思考,看看C#中decimal 在开发中常常C#来读取数据库存储的值,就必要要定义相应的变量来存取。在C#里decimal是128位的精确数据类型,大致范围是 ±1.0 × 10^-28 到 ±7.9 × 10^28,比sql Decimal的最大范围要小一些,但是当前人类的99.999999……999999999%的应用应该是完全可以满足的(见参考3)。decimal在计算机中是如何存储? (见参考4)。   参考1: decimal 和 numeric (Transact-SQL) 参考2: SQL SERVER – Difference and Explanation among DECIMAL,FLOAT and NUMERIC
参考3: decimal (C# Reference) 参考4: http://topic.csdn.net/u/20090505/14/2859ab0f-579a-467b-b03a-c792bfb98bc6.html 总结

以上是内存溢出为你收集整理的不小心又中了decimal的埋伏——重新捋一下decimal的相关知识全部内容,希望文章能够帮你解决不小心又中了decimal的埋伏——重新捋一下decimal的相关知识所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/sjk/1180611.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存