【发布时间】:2008-11-07 19:40:32
【问题描述】:
为什么当我在 SQL Server 中将 40.54 的值保存到 Real 类型的列时,它返回给我的值更像 40.53999878999 而不是 40.54?我已经看过几次了,但从来没有弄清楚为什么会发生这种情况。有没有其他人遇到过这个问题,如果有的话?
【问题讨论】:
标签: sql-server types
为什么当我在 SQL Server 中将 40.54 的值保存到 Real 类型的列时,它返回给我的值更像 40.53999878999 而不是 40.54?我已经看过几次了,但从来没有弄清楚为什么会发生这种情况。有没有其他人遇到过这个问题,如果有的话?
【问题讨论】:
标签: sql-server types
看看What Every Computer Scientist Should Know About Floating Point Arithmetic。
计算机中的浮点数不能精确地表示小数。相反,它们代表 二进制 分数。大多数小数没有作为二进制分数的精确表示,因此需要进行一些舍入。当这样一个四舍五入的二进制分数被转换回一个十进制分数时,你就会得到你描述的效果。
为了存储货币值,SQL 数据库通常提供 DECIMAL 类型来存储精确的十进制数字。这种格式对计算机来说处理效率稍低,但在您想避免小数舍入错误时非常有用。
【讨论】:
1/2 可以在两个系统上精确表示。
浮点数使用二进制小数,它们与小数不完全对应。
对于金钱,最好将美分数存储为整数,或使用十进制数类型。例如,Decimal(8,2) 存储 8 位数字,包括 2 位小数 (xxxxxx.xx),即精确到分。
【讨论】:
简而言之,由于几乎相同的原因,三分之一不能精确地用十进制表示。详情请查看 David Goldberg 的经典论文“What Every Computer Scientist Should Know About Floating-Point Arithmetic”。
【讨论】:
澄清一下,存储在计算机中的浮点数的行为与此处其他帖子的描述相同,因为如上所述,它以二进制格式存储。 这意味着除非它的值(值的尾数和指数分量)是 2 的幂,并且不能精确表示。
另一方面,有些系统以十进制形式存储小数(例如 SQL Server Decimal 和 Numeric 数据类型,以及 Oracle Number 数据类型),因此它们的内部表示对于任何幂数都是精确的10 次方。但不是 10 次方的数字不能精确表示。
【讨论】: