如何从浮点数获得模数

时间:2014-03-12 10:33:38

标签: php modulo

我有:

$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)

任何想法?

3 个答案:

答案 0 :(得分:1)

其他可能性:float as string modulo: - )

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 :(得分: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()以使其适用于负数。

答案 2 :(得分:0)

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));
    }