处理mysql中有效数字的问题将float转换为double

z3yyvxxp  于 2021-06-19  发布在  Mysql
关注(0)|答案(1)|浏览(666)

我将数据从一个表插入mariadb数据库中的另一个表,其中第一个表中的列是 FLOAT ,第二个是 DOUBLE . 数据可以有任何大小、精度和小数位数的值。
下面是我直接复制时值的变化:

INSERT INTO data2 (value) SELECT value FROM data1

这些值是随机的额外有效数字:

FLOAT in data1           DOUBLE in data2
-0.000000000000454747    -0.0000000000004547473508864641
-122.319                 -122.31932830810547
14864199700              14864220160
``` `CAST(value AS DECIMAL(65,30))` 生成与上面第2列完全相同的值,只是我看到了尾随的零。
但当我这么做的时候

UPDATE data2 SET value = 14867199700 WHERE id = 133025046;

这个 `DOUBLE` 值被接受。
我是否必须将所有值导出到sql脚本并重新导入它们?难道没有更好的办法吗?
尽管我花了好几个小时尝试解决这个问题,但我还没有找到解决方案,尽管它的性质有限。我可以看出这个问题困扰着所有的技术,不仅仅是mariadb或数据库,所以我可能只是在某个地方错过了答案。stackoverflow正在拼命地尝试用我以前没有见过的新建议功能来指导解决方案,但不幸的是,它们没有帮助,就像其他建议的答案一样。
3bygqnnd

3bygqnnd1#

你的测试用例有缺陷。您正在输入十进制数字,而不只是测试数据的传输 FLOATDOUBLE . UPDATE tbl SET double_col = float_col 将始终复制完全相同的值。这是因为 DOUBLE 表示是表示的超集 FLOAT 表示(53比24位精度;等等)。
文字,带小数位: UPDATE tbl SET double_col = 123.456 由于从小数点到小数点的四舍五入,数字会被弄乱 DOUBLE . 同上 float_col . 此外,损坏的结果将是不同的!
孔号文字: UPDATE tbl SET double_col = 14867199700 将准确地存储。但如果你把同样的文字放进 FLOAT ,它将四舍五入到24位,因此无法准确存储。在大约7位有效数字处,对于 FLOAT 16岁左右 DOUBLE . 本例中的文字有9个有效数字(在忽略后面的零之后)。
这只是你能做的噩梦的一个样本。
你必须考虑 FLOAT 以及 DOUBLE 大概。你不应该为了平等而比较;你不知道是什么把最后一点的值弄乱了。
另外,您不应该试图猜测mysql何时在中执行表达式 DECIMAL 而不是 DOUBLE .
而且,请记住,除法通常是不精确的,因为四舍五入到一些位数或小数。
14864199700的“尾数”是

1.10111010111111001101100 (binary of FLOAT : 24 bits including 'hidden' leading bit)
    1.1011101011111100110110000000101000000000000000000000 (binary of DOUBLE)
                                  ^ ^  (lost in FLOAT)

每一个都乘以2的相同幂。这个 DOUBLE 精确到14864199700。这个 FLOAT 丢失了指向的位。
你可以和这样的人一起玩https://gregstoll.dyndns.org/~gregstoll/floattohex/
信不信由你,以前情况更糟。由于四舍五入的错误,人们将被收取0.00美元的费用。或者应该是1+1的结果显示为1.9999999。

相关问题