mysql - 如何将十进制计算结果存储在mysql中并像在内存中一样将其检索回来

标签 mysql floating-point precision floating-accuracy

MySQL 文档 says :

The DECIMAL and NUMERIC types store exact numeric data values. These types are used when it is important to preserve exact precision, for example with monetary data.

我对该列 decimal_column DECIMAL(31,30) 进行了测试。

insert into tests (decimal_column) values(1/3);

然后检查已存储的内容给出了这个

select * from tests ;
> result : 0.333333333000000000000000000000

然后用这个查询反转数学运算得到这个

select decimal_column*3 from test;
> result: 0.999999999000000000000000000000

我期望得到整数“1”,就像我们在计算器和 Excel 工作表中所做的那样!像这样

 #calculator or excel sheet
 >input: 1 / 3
 >result: 0.3333333333333333333333333333333333
 >input: * 3
 >result: 1

1- 为什么 MySQL 没有存储 (1/3) 的精确二进制表示,因此我可以在我的计算中再次使用该结果,因为它们像计算器或 Excel 工作表一样在内存中.

2- 如何在 mysql 中存储 (1/3) 的结果,因为它们在计算期间在内存中,所以我可以检索准确的值并执行类似 3 * $storedValue 的操作,以得到 1 的整数,就像我们在计算器或 Excel 工作表中所做的那样。

最佳答案

问题不在存储中。在您的示例中,该值在存储到表中之前已损坏。

不幸的是,如果你写 1/3,将使用默认表示计算(并插入):

SELECT 1/3

0.333333333

如您所见,精度不够。

另一个问题是,当您向服务器发送常量(1 或 3)时,您需要使用连接器,这可能需要自由与值(value)。例如,它可能认为“1”和“3”是整数,并且它们的结果将被视为整数。所以你得到“1/3 = 0”,但是“1./3 = 0.333333”,因为“1”中的点。使连接器意识到它需要使用其默认 float 。而且你只得到六个 3,因为连接器的“默认 float ”有 6 个数字。然后将其存储到数据库中,但为时已晚。您正在以高精度存储一个已被截断为低精度的值。

您可以尝试从一开始就强制转换常量。您可以使用 1 作为足够大的小数来代替“1”。我在这里使用您的 31,30,但请检查您是否不需要存储更大的数字。可能,“31,20”会更好。

mysql> SELECT 1/3 UNION SELECT CAST(1 AS DECIMAL(31,30))/CAST(3 AS DECIMAL(31,30));
+----------------------------------+
| 1/3                              |
+----------------------------------+
| 0.333333333000000000000000000000 |
| 0.333333333333333333333333333333 |
+----------------------------------+
2 rows in set (0.00 sec)

虽然很别扭,但效果应该会更好。另外,我认为只需要在表达式中转换 一个 值;然后 MySQL 将根据需要升级所有涉及的数量。因此,将 CAST(0 AS DECIMAL(x,y)) 添加到求和中并将 CAST(1 AS DECIMAL(x,y)) 添加到乘法中可能就足够了。

mysql> SELECT 3*CAST(1 AS DECIMAL(31,30))/CAST(3 AS DECIMAL(31,30));
+-------------------------------------------------------+
| 3*CAST(1 AS DECIMAL(31,30))/CAST(3 AS DECIMAL(31,30)) |
+-------------------------------------------------------+
|                      1.000000000000000000000000000000 |
+-------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT CAST(1 AS DECIMAL(31,30))*1/3;
+----------------------------------+
| CAST(1 AS DECIMAL(31,30))*1/3    |
+----------------------------------+
| 0.333333333333333333333333333333 |
+----------------------------------+
1 row in set (0.00 sec)

请注意,不起作用,因为乘法具有更高的优先级:

mysql> SELECT CAST(0 AS DECIMAL(31,30))+1/3;
+----------------------------------+
| CAST(0 AS DECIMAL(31,30))+1/3    |
+----------------------------------+
| 0.333333333000000000000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

关于mysql - 如何将十进制计算结果存储在mysql中并像在内存中一样将其检索回来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42833474/

相关文章:

mysql - 排名排行榜 - MySQL

mysql - 在不同数据库的表之间传输行

mysql - mariadb 10.1.13 加莱拉集群 : error

PHP整数舍入问题

mysql - 更改端口号后 xampp 未启动 mysql

java - 以最小的精度损失将 float 转换为 short

python - 如何检查用户输入是否为 float

C++ float vs double cout setprecision 奇怪之处(新手)

math - float 学有问题吗?

C算术表达式与printf不一致并赋值给另一个变量