MySQL舍入行为未按预期工作。。?

MySQL舍入行为未按预期工作。。?,mysql,floating-point,rounding,precision,Mysql,Floating Point,Rounding,Precision,可以找到这些术语。 其中,他们承诺近似值(浮点值、双精度值)的四舍五入为半_偶数。但当我尝试同样的方法时,我无法说出文件中所说的话。对于双数据类型,它显然起到了一半的作用。这里有我遗漏的东西吗 CREATE TABLE `doubleValues` ( `val` double DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; select* from doubleValues; +-------+ | val | +-------+

可以找到这些术语。 其中,他们承诺近似值(浮点值、双精度值)的四舍五入为半_偶数。但当我尝试同样的方法时,我无法说出文件中所说的话。对于双数据类型,它显然起到了一半的作用。这里有我遗漏的东西吗

CREATE TABLE `doubleValues` (
  `val` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

select* from doubleValues;
+-------+
| val   |
+-------+
| 1.245 |
| 0.555 |
+-------+

select round(val,2) from doubleValues;
+--------------+
| round(val,2) |
+--------------+
|         1.25 |
|         0.56 |
+--------------+
2 rows in set (0.00 sec)

从您将请求链接到的文档中:

对于近似值数字,结果取决于C库。在许多系统上,这意味着ROUND()使用“舍入到最近的偶数”规则:具有任何小数部分的值舍入到最近的偶数整数

换句话说:舍入方法未定义。


无论如何:为什么要使用近似类型呢?你需要那么多数字吗?我很难想象一个数据库会出现这种情况。可能是一些天文数据库。

从您将请求链接到的文档中:

对于近似值数字,结果取决于C库。在许多系统上,这意味着ROUND()使用“舍入到最近的偶数”规则:具有任何小数部分的值舍入到最近的偶数整数

换句话说:舍入方法未定义。


无论如何:为什么要使用近似类型呢?你需要那么多数字吗?我很难想象一个数据库会出现这种情况。可能是一些天文数据库。

二进制浮点中不存在数字1.245和0.555;它们并不完全具有代表性。您看到的“1.245”和“0.555”可能是1.245000000106581410364015027880666864013671875和0.55500000000000004884898130835068777863979339599609375。这些是64位二进制IEEE-754浮点中最接近1.245和0.555的值。(虽然它们以十进制表示时很长,但以二进制表示时很短。)


当四舍五入到两个小数点时,必须四舍五入的部分在四舍五入位置略高于½。第一个是.5000000000000106581410364015027880666864013671875,第二个是.5000000000000048849130835068877863979339599609375。因此,当分数四舍五入正好为½时,关于如何操作的规则不起作用。它们都在½以上,因此被四舍五入。

二进制浮点中不存在数字1.245和0.555;它们并不完全具有代表性。您看到的“1.245”和“0.555”可能是1.245000000106581410364015027880666864013671875和0.55500000000000004884898130835068777863979339599609375。这些是64位二进制IEEE-754浮点中最接近1.245和0.555的值。(虽然它们以十进制表示时很长,但以二进制表示时很短。)


当四舍五入到两个小数点时,必须四舍五入的部分在四舍五入位置略高于½。第一个是.5000000000000106581410364015027880666864013671875,第二个是.5000000000000048849130835068877863979339599609375。因此,当分数四舍五入正好为½时,关于如何操作的规则不起作用。这两个数值都在½以上,因此它们被四舍五入。

您使用的不是近似值,而是精确值。同时,作者还表示,取整一半可能取决于底层的C库;这种情况并不总是发生。@TimBiegeleisen我对“val”列使用了双数据类型。根据MySQL,FLOAT和DOUBLE是近似的数字数据类型。请参考:通过检查下面托尔斯滕的回答,你关于加倍的回答是对的;舍入行为未定义。您使用的不是近似值,而是精确值。同时,作者还表示,取整一半可能取决于底层的C库;这种情况并不总是发生。@TimBiegeleisen我对“val”列使用了双数据类型。根据MySQL,FLOAT和DOUBLE是近似的数字数据类型。请参考:通过检查下面托尔斯滕的回答,你关于加倍的回答是对的;舍入行为未定义。这是一个旧表,我们无法更改它:(对于任何给定的系统,有没有办法知道舍入方法以确保知道呢?)如果你将列从双精度更改为十进制,会发生什么不好的事情?我看不出有任何问题。在这样的更改中,会出现奇怪的代码。至于舍入浮点:这是偶然的。你看到的1.245可能会存储在其中r为1.2450001或1.2449999-谁知道呢。这就是近似数据的“魅力”。这是一个旧表,我们无法更改它:(对于任何给定的系统,有没有办法知道舍入方法以确保知道呢?)如果你将列从双精度更改为十进制,会发生什么不好的事情?我看不出有任何问题。在这样的更改中,会出现奇怪的代码。至于舍入浮点:这是偶然的。你看到的1.245可能会存储在其中r为1.2450001或1.2449999——谁知道呢。这就是近似数据的“魅力”。