为啥 SQL 浮点数与 C# 浮点数不同
Posted
技术标签:
【中文标题】为啥 SQL 浮点数与 C# 浮点数不同【英文标题】:Why is a SQL float different from a C# float为什么 SQL 浮点数与 C# 浮点数不同 【发布时间】:2010-09-12 11:01:15 【问题描述】:您好,我从 DataSet 中的 DataTable 中提取了一个 DataRow。我正在访问在 SQL 中定义为浮点数据类型的列。我正在尝试将该值分配给局部变量(c# float 数据类型),但得到一个 InvalidCastExecption
DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65);
_AccelLimit = (float)exercise["DefaultAccelLimit"];
现在,玩弄这个我确实让它工作了,但它没有任何意义,而且感觉不对。
_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];
谁能解释我在这里缺少什么?
【问题讨论】:
【参考方案1】:它“感觉不对”的原因是因为 C# 对 unboxing 和 casting 使用相同的语法,这是两个非常不同的东西。 exercise["DefaultAccelLimit"]
包含一个双精度值,被装箱为一个对象。需要(double)
才能将对象拆箱重新转换为双精度对象。前面的 (float)
然后 casts 将双精度值转换为浮点值。 C# 不允许在同一操作中进行装箱和强制转换,因此必须先取消装箱,然后再进行强制转换。
即使演员表是非破坏性的也是如此。如果将浮点数装箱为要转换为双精度的对象,则可以这样做:(double)(float)object_var
。
【讨论】:
【参考方案2】:我认为这里已经回答了主要问题,但我觉得有必要为问题的部分添加一些内容,说明这有效。
_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];
这个“有效”的原因和它“感觉不对”的原因是你在第二次演员(左边的那个)之前将双精度降级为浮点数,所以你正在失去精度并有效地告诉编译器认为可以截断返回的值。
一句话,这行表明...... 获取一个对象(在这种情况下恰好包含一个双精度对象) 将对象转换为双精度(丢失所有对象包装) 将双精度转换为浮点数(失去双精度的所有精细精度)
例如如果值是说 0.0124022806089461 并且您执行上述操作,那么 AccelLimit 的值将是 0.01240228
因为这是 c# 中的浮点数可以从双精度值中获得的程度。 这是一件危险的事情,我很确定它也是截断而不是四舍五入,但有人可能想确认这一点,因为我不确定。
【讨论】:
【参考方案3】:如果您计划对数据执行数学计算,通常您永远不会希望在 SQL Server(或真实)中使用浮点数,因为它是不精确的数据类型,并且会引入计算错误。如果需要精度,请改用十进制数据类型。
【讨论】:
大多数数学和工程计算都可以。现在,财务和会计计算当然是不同的。【参考方案4】:Microsoft SQL Server 中的浮点数相当于 C# 中的 Double。原因是浮点数只能逼近十进制数,浮点数的精度决定了该数字逼近十进制数的准确程度。 Double 类型表示双精度 64 位浮点数,其值范围从负 1.79769313486232e308 到正 1.79769313486232e308,以及正或负零、PositiveInfinity、NegativeInfinity 和 Not-a-Number (NaN)。
【讨论】:
【参考方案5】:SQL 中的浮点数是 CLR (C#/VB) 中的 Double。 MSDN 上有a table of SQL data types with the CLR equivalents。
【讨论】:
它们相似但肯定不等价。根据 IEEE 规范,Double 支持 +Infinity、-Infinity 和 NaN 的值,但 SQL float 绝对不支持。并会抛出溢出错误。希望 MSDN 将其添加到他们的信息页面。 好的。那么你的答案是什么?【参考方案6】:根据 the documentation for SQLDbType,SQL 浮点数是双精度。
【讨论】:
它们相似但肯定不等价。根据 IEEE 规范,Double 支持 +Infinity、-Infinity 和 NaN 的值,但 SQL float 绝对不支持。并且会抛出溢出错误。 我同意 Alain May 的 cmets,但我还不明白为什么。我见过 .net double 表示会破坏 SQL 浮点数的情况。示例包括无穷大值和某些接近零的负指数。我怀疑 MS 针对存储效率进行了优化。 @RaoulRubin:见MSDN documentation for TSQL floats。他们从未提及 IEEE 合规性,并声明它遵循一些未命名的 ISO 标准。快速搜索会得到 ISO/IEC 10967,它声明它与 IEEE 754 兼容,但不能保证完全实现。以上是关于为啥 SQL 浮点数与 C# 浮点数不同的主要内容,如果未能解决你的问题,请参考以下文章
为啥 % 运算符不能用于 C/C++ 中的浮点数但可以用于 Java 和 C#? [复制]