php将precision float保存到mysql中,最终得到四舍五入的结果字段

inn6fuwd  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(439)

我读过所有关于浮点数的算术,但我只是想准确地存储该死的东西。
我有一个mysql字段,类型为 DECIMAL (40,20) .
我正在用php保存一个值 46457.67469999996 . 使用此值更新记录后,最终结果是 46457.67470000000000000000 . 不知道为什么它会被舍入保存到数据库。
该值未事先转换为字符串或任何内容。传入pdo的字段值是我希望保存的值,它以浮点形式返回。。。可能是因为我将php浮点保存为mysql十进制类型,在该类型中进行舍入?
我错过了什么?
编辑:添加了有问题的示例代码

// Query placeholder variables.  Hard-coded for the example test
$query_vars = array(
    ":vendor_id"                    => 33154,
    ":year"                         => 2018,
    ":coop_committed_dollar"        => 46457.67469999996,
    ":coop_committed_dollar_update" => 46457.67469999996
);

$statement = "  INSERT INTO vendor_data_yearly
                (vendor_id, year, coop_committed_dollar) VALUES
                (:vendor_id, :year, :coop_committed_dollar)
                ON DUPLICATE KEY UPDATE
                    coop_committed_dollar = :coop_committed_dollar_update;";
$query = $connection->conn->prepare($statement);
$query->execute($query_vars);

当我运行这个时 coop_committed_dollar46457.67470000000000000000 . 我所做的一切都是合法的。
可能的解决方案

// Note that I am casting the string using the BC Math library.
// I dunno how to just initialize the number (lame documentation), so I'm adding 0 to it.
$number = "46457.674699999967";
$number = bcadd("46457.674699999967", 0, 20);

$query_vars = array(
    ":vendor_id"                    => 33154,
    ":year"                         => 2018,
    ":coop_committed_dollar"        => $number,
    ":coop_committed_dollar_update" => $number
);

$statement = "  INSERT INTO vendor_data_yearly
                (vendor_id, year, coop_committed_dollar) VALUES
                (:vendor_id, :year, :coop_committed_dollar)
                ON DUPLICATE KEY UPDATE
                    coop_committed_dollar = :coop_committed_dollar_update;";
$query = $conn->prepare($statement);
$query->execute($query_vars);

这将产生db中预期的数字。
我找到的唯一正确的解决办法
我处理的数据是通过ajax传入的。我不得不采取一些措施让它正常工作。
使用 ini_set('precision', 20); 在通过ajax发送之前,手动将有问题的数据设置为一个字符串,这样php就不会对其进行舍入、扩展和额外的浮点疯狂、填充等操作。
我发现php不能让我可靠地处理来自脚本作用域(ajax)之外的变量集的大量数据。一旦php掌握了这个数字,它就会做它必须做的事情,以使它成为一个有意义的浮点数。
如果有人对这种特殊情况有更好的解决方案,我洗耳恭听:)

qyswt5oh

qyswt5oh1#

问题是php的精度不允许您存储您认为正在存储的确切数字。当你设置 ":coop_committed_dollar" => 46457.67469999996 php实际上是将其存储为不同的值,具体取决于精度。
解决方案是在php中将值存储为字符串,而不是浮点数。
既然你的问题是:“我遗漏了什么”,我会尽力提供一个答案。基本上可以归结为使用二进制表示在内部存储浮点数。由于46457.6746999996不能完全是二进制的(它以一个无穷大的数字结束,类似于基数-10中的33%(.3333…),因此根据php的精度(在php ini中设置)使用最接近的舍入。
我刚才问的这个问题得到了很好的解释。
在您的特定情况下,通过ajax发送的值在服务器端被php解析时似乎也被存储为一个float。您希望将其存储为字符串。如果您使用的是json\u decode,请添加以下选项:json\u bigint\u as\u string。

相关问题