使用浮点数进行filter_var_array会导致结果中的小数位数过多

filter_var_array with floats causes too many decimal places in result

提问人:skaldesh 提问时间:3/17/2017 最后编辑:skaldesh 更新时间:3/30/2017 访问量:769

问:

我对 filter_var_array 函数有疑问,特别是“FILTER_VALIDATE_FLOAT”标志,它返回的浮点数点数太多

代码优先:

if (property_exists($this->rawRequest, $varName)) {
    $res = filter_var_array($this->rawRequest->$varName, FILTER_VALIDATE_FLOAT);
}

这是我的代码,我在其中验证通过JSON
从客户端收到的参数 rawRequest 是一个 stdClass,如下所示(用 var_export 打印):

stdClass::__set_state(
     array(
        'Action' => 'CreateObject',
        'Template' => 'none',
        'LatLng' => array (
            0 => '48.14914653539144',
            1 => '11.577623201171932',
        )
)

使用 filter_var_array 筛选“LatLng”参数后,结果如下所示:

'LatLng' => array (
    0 => 48.149146535391433732957206666469573974609375,
    1 => 11.5776232011719315551090403459966182708740234375,
)

为什么会这样?

我什至无法用round()解决这个问题,将类型转换为float,转换为字符串并返回float,我试图减去0.000000001,然后再次添加0.000000001,没有任何帮助

更新:我在同一台机器,同一台apache服务器上编写了以下小测试脚本:

<?php

$test = '48.158308230848306';
$test2 = (float) $test;
$test3 = floatval($test);

echo($test2);
echo('<br />');
echo($test3);
exit(0);

输出如下:

48.158308230848
48.158308230848

这就是我所期望
的,我用我的 prod 代码重新测试了它并使用 floatval() 和类型转换来浮动,但它不起作用。我不知道,唯一的区别是,在生产代码中,输入是json,我用以下代码解析它:

json_decode(file_get_contents('php://input'))
php 浮点 精度 float-accuracy

评论

0赞 Thomas Padron-McCarthy 3/18/2017
这就是浮点数的作用。如果要将 48.14914653539144 存储为浮点值,则无法精确存储它,而是获得另一个数字。浮点数学坏了吗?
0赞 Thomas Padron-McCarthy 3/18/2017
但是,更仔细地观察你的数字,这些数字是否被正确复制?由于输出数字与输入数字有很大不同,因此超出了正常浮点表示错误的预期。
0赞 skaldesh 3/23/2017
哦,不对不起,固定了数字,它们来自不同的测试
0赞 skaldesh 3/23/2017
我不认为这是重复的,我很清楚这个问题。我已经准备好听听如何解决我的问题,因为filter_var_array只是损坏了我的字符串输入,之后我所做的任何事情都无法修复我得到的这个奇怪的浮点输出
0赞 skaldesh 3/23/2017
我知道浮点数只是小数的近似值,我知道,但是我该如何四舍五入呢?

答:

3赞 skaldesh 3/30/2017 #1

所以,我终于找到了问题的答案

问题从来都不是功能,实际上,问题发生得更早。
通过检索 POST 参数后,一切仍然正常。
但是当我用 解码返回的字符串时,浮点值在此过程中被序列化,从而获得更高的精度。
filter_var_array()file_get_contents("php://input")json_decode()

我找到了两种方法来“解决”这个问题:

  • 更改 php 中的“serialize_precision”参数.ini(我的默认为 100,将其设置为与我的“precision”参数相同 成功)
    我不推荐这种方法,因为更改此参数的影响可能会在其他地方造成毁灭性的影响
  • 将请求中的浮点数括在引号中
    因此,将 JSON {“test”: 48.58495135846} 更改为 {“test”: “48.58495135846”}
    这可以防止浮点数的序列化,因为它现在实际上是一个字符串

希望这对其他人有所帮助,也许这已经是常识了,但我为此扯了扯头发。