如何从浮点数取模

问题描述 投票:0回答:3

我有:

$value = 0.57;
$step = 0.01;

我想检查$ value / $ step是否为整数。另外,有时$ value为负数。

我得到的是:

$value/$step -> 57
is_int($value/$step) -> false
and the best one:
floor($value/$step) -> 56 (I assume that 57 is really 56.9999999(9) )
$a - $b * floor($a / $b) -> 0.0099999(9)
($value/$step)%1 -> 0 (ok, but % doesn't work if it is really a float)
fmod($value/$step) -> 0.999999999(9)

任何想法?

php modulo
3个回答
1
投票

其他可能性:以字符串取模形式:-)浮动

function float_modulo($value, $step) {
    $str_value = strval($value);
    $float_part_value = substr($str_value, strpos($str_value, ".") + 1);
    $str_step = strval($step);
    $float_part_step = substr($str_step, strpos($str_step, ".") + 1);    
    return intval($float_part_value) % intval($float_part_step);
}

1
投票

OP解决方案

public static function isZero($number, $precision = 0.0000000001)
    {
        $precision = abs($precision);
        return -$precision < (float)$number && (float)$number < $precision;
    }
    public static function isEqual($number1, $number2)
    {
        return self::isZero($number1 - $number2);
    }
    public static function fmod($number1, $number2)
    {
        //$rest = self::sfmod($number1, $number2);

        if ($number2<0)
        {
            $rest = $number1 - $number2 * ceil($number1/$number2);
        }
        else if ($number2>0)
        {
            $rest = $number1-$number2*floor($number1/$number2);
        }

        if (self::isEqual($rest, $number2)) {
            return 0.0;
        }
        if (mb_strpos($number1, ".") === false) {
            $decimals1 = 0;
        } else {
            $decimals1 = mb_strlen($number1) - mb_strpos($number1, ".") - 1;
        }
        if (mb_strpos($number2, ".") === false) {
            $decimals2 = 0;
        } else {
            $decimals2 = mb_strlen($number2) - mb_strpos($number2, ".") - 1;
        }
        return (float)round($rest, max($decimals1, $decimals2));
    }

0
投票

我不知道它是否有足够的帮助,但我认为您可以从四舍五入后的值中减去除法结果,并将其与epsilon值进行比较,如下所示:

$value = 0.57;
$step = 0.01;
$epsilon = 0.00000001; // less decimals means lower precision
var_dump(abs(round($value/$step) - $value/$step) < $epsilon);

将其包装在函数中,然后将其命名为test_integer,或者根据需要查看它是否对您有用。

LE:添加了abs()以使其适用于负数。

© www.soinside.com 2019 - 2024. All rights reserved.