PHP计算除法整数

PHP calculate integer of division

我想计算除法的整数部分。分子和分母(尤其是它们的精度)不应更改,因为它可能会从一种计算变为另一种计算,分母也是一个例子,它的整数部分和小数部分可能不同。

我尝试使用 floor, ceil, round,但其中 none 产生了正确的结果。 请看下面的代码,也许你会发现错误:

<?php

$valueArr = [
    // should return 1999
    199.90,
    199.92,
    199.95,
    199.97,

    // should return 2000
    200.00,
    200.02,
    200.05,
    200.07,

    // should return 2001
    200.10,
    200.12,
    200.15,
    200.17,
];

$denominator = 0.1;

$resultArr = [];

foreach ($valueArr as $value) {
    $key = (string) $value;
    $result = floor($value / $denominator);
    $resultArr[$key] = $result;
}

echo "Denominator:\n";
var_dump($denominator);
echo "\n";

print_r($resultArr);

给出结果:

Denominator:
float(0.1)

Array
(
    [199.9] => 1999
    [199.92] => 1999
    [199.95] => 1999
    [199.97] => 1999
    [200] => 2000
    [200.02] => 2000
    [200.05] => 2000
    [200.07] => 2000
    [200.1] => 2000
    [200.12] => 2001
    [200.15] => 2001
    [200.17] => 2001
)

其中:

    [200.1] => 2000

是错误的,因为 (200.1 / 0.1) 的整数部分是 2001.

你知道如何为上面的 $valueArr 生成正确的结果吗?我做错了什么?

我正在使用 PHP 7.3.8 (cli)

我使用 bcdiv() 得到了正确的结果。

$result = bcdiv($value,$denominator);

我一直用 BcMath,对我来说似乎更可靠。

你没有做错任何事。这是电脑的问题。很难在固定的 space.

中准确表示浮点数

试试这个

foreach ($valueArr as $v) {
    $resultArr []= floor($v * (1 / $denominator));
}

我的建议是尝试将除法运算转换为乘法。

在你的情况下,除以 0.1 === 乘以 10。所以,使用它。

所以您要 运行 进入这里的两个问题。首先是一般浮点数缺乏精度,其次是 PHP 在您有机会使用 bcdiv.

之类的东西之前自动将您的输入强制转换为浮点数

因此:第一步是将您的输入数字存储为字符串,这样您就不会因为解析器将它们解释为浮点数而失去精度。然后对它们使用bcdiv

因为你只是在整数部分和 bcdiv returns 成功的字符串之后,我们可以用字符串函数删除小数部分。

<?php

$valueArr = [
    // should return 1999
    '199.90',
    '199.92',
    '199.95',
    '199.97',

    // should return 2000
    '200.00',
    '200.02',
    '200.05',
    '200.07',

    // should return 2001
    '200.10',
    '200.12',
    '200.15',
    '200.17',

    '381736192374124241.294',
];

$denominator = '0.1';

$resultArr = [];

foreach ($valueArr as $value) {
    $key = (string) $value;
    $result = explode('.', bcdiv($value, $denominator))[0];
    $resultArr[$key] = $result;
}

echo "Denominator:\n";
var_dump($denominator);
echo "\n";

print_r($resultArr);

如果您想对 bcdiv 的输出进行舍入、ceil、floor 之类的操作,请查看此答案:

如果您没有 BcMath 扩展附带的 bcdiv 您可以使用 sprintf() function to achieve a proper result with the floor() 并且即使在分母是小于 0.0001.

的浮点数的情况下也没有任何问题

而不是:

$result = floor($value / $denominator);

使用这个:

$result = floor(sprintf('%f', $value / $denominator));

你会得到正确的:

[200.1] => 2001