diff --git a/src/Symfony/Component/Validator/Constraints/DivisibleByValidator.php b/src/Symfony/Component/Validator/Constraints/DivisibleByValidator.php index c9455d71a17ef..a64ad7be437a8 100644 --- a/src/Symfony/Component/Validator/Constraints/DivisibleByValidator.php +++ b/src/Symfony/Component/Validator/Constraints/DivisibleByValidator.php @@ -23,7 +23,26 @@ class DivisibleByValidator extends AbstractComparisonValidator */ protected function compareValues($value1, $value2) { - return (float) 0 === fmod($value1, $value2); + $value1 = \abs($value1); + $value2 = \abs($value2); + $epsilon = 0.0000001; + + // can't divide by 0 + if ($value2 < $epsilon) { + return false; + } + + // 0 is divisible by everything + if ($value1 < $epsilon) { + return true; + } + + // if the divisor is larger than the dividend, it will never cleanly divide + if ($value2 > $value1) { + return false; + } + + return \abs($value1 - round($value1 / $value2) * $value2) < $epsilon; } /** diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByValidatorTest.php index b4812ca8d5c55..117f0ef1f401b 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/DivisibleByValidatorTest.php @@ -46,6 +46,7 @@ public function provideValidComparisons() array(42, 21), array(3.25, 0.25), array('100', '10'), + array(4.1, 0.1), ); } @@ -69,6 +70,7 @@ public function provideInvalidComparisons() array(10, '10', 3, '3', 'integer'), array(10, '10', 0, '0', 'integer'), array(42, '42', INF, 'INF', 'double'), + array(4.15, '4.15', 0.1, '0.1', 'double'), array('22', '"22"', '10', '"10"', 'string'), ); }