【问题标题】:Real vs. Floating Point vs. Money真实 vs. 浮点 vs. 金钱
【发布时间】:2008-11-07 19:40:32
【问题描述】:

为什么当我在 SQL Server 中将 40.54 的值保存到 Real 类型的列时,它返回给我的值更像 40.53999878999 而不是 40.54?我已经看过几次了,但从来没有弄清楚为什么会发生这种情况。有没有其他人遇到过这个问题,如果有的话?

【问题讨论】:

标签: sql-server types


【解决方案1】:

看看What Every Computer Scientist Should Know About Floating Point Arithmetic

计算机中的浮点数不能精确地表示小数。相反,它们代表 二进制 分数。大多数小数没有作为二进制分数的精确表示,因此需要进行一些舍入。当这样一个四舍五入的二进制分数被转换回一个十进制分数时,你就会得到你描述的效果。

为了存储货币值,SQL 数据库通常提供 DECIMAL 类型来存储精确的十进制数字。这种格式对计算机来说处理效率稍低,但在您想避免小数舍入错误时非常有用。

【讨论】:

  • 实际上,计算机的处理速度明显慢(大约十倍,主要是由于缺乏硬件支持),但对于大多数应用程序来说,速度并不重要因为数值运算远不是瓶颈。
  • 浮点数不能准确地表示 一些 小数。现实生活中的实数也不能准确地表示 some 分数。例如,1/2 可以在两个系统上精确表示。
【解决方案2】:

浮点数使用二进制小数,它们与小数不完全对应。

对于金钱,最好将美分数存储为整数,或使用十进制数类型。例如,Decimal(8,2) 存储 8 位数字,包括 2 位小数 (xxxxxx.xx),即精确到分。

【讨论】:

  • 我很乐意让你们两个都因为回答得好而获得积分。我们使用的是货币价值,而不是存储美分。你认为这也是一种很好的做法吗?
  • 存储美分是个坏消息。金融机构在计算中经常使用小数美分,有时也需要存储它们。我曾经参与过一个项目,在部署美分存储应用程序后出现了这个问题。很丑。
  • 请注意,Decimal(8,2) 实际上不是 xxxxxx.xx 而不是 xxxxxxxx.xx 吗?定义中的8是指小数点前后的总位数。
【解决方案3】:

简而言之,由于几乎相同的原因,三分之一不能精确地用十进制表示。详情请查看 David Goldberg 的经典论文“What Every Computer Scientist Should Know About Floating-Point Arithmetic”。

【讨论】:

    【解决方案4】:

    澄清一下,存储在计算机中的浮点数的行为与此处其他帖子的描述相同,因为如上所述,它以二进制格式存储。 这意味着除非它的值(值的尾数和指数分量)是 2 的幂,并且不能精确表示。

    另一方面,有些系统以十进制形式存储小数(例如 SQL Server Decimal 和 Numeric 数据类型,以及 Oracle Number 数据类型),因此它们的内部表示对于任何幂数都是精确的10 次方。但不是 10 次方的数字不能精确表示。

    【讨论】:

      猜你喜欢
      • 2015-01-15
      • 2017-01-15
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-04
      • 2015-12-30
      相关资源
      最近更新 更多