Сопоставление php integer и float

У меня есть следующий код

$amount1 = 7299; $amount2 = 72.9875; $amount2_in_cents = round($amount2, 2) * 100; if ($amount1 != $amount2_in_cents) { echo "Amount $amount1 != $amount2_in_cents\n"; var_dump($amount1); var_dump($amount2_in_cents); } else { echo "Amounts matched"; } 

и это результат

 Amount 7299 != 7299 int(7299) float(7299) 

Теперь я понимаю, что floats и int различны, но, учитывая округление, я ожидал, что два значения будут соответствовать. И я решил это, бросив на int.

Поэтому мой вопрос: почему это сравнение не работает так, как я ожидал (оба значения совпадают)?

Обратите внимание на большое красное предупреждение в Руководстве по PHP !

Никогда не ожидайте ничего, сравнивая поплавки. Результат раунда, даже если точность 0, по-прежнему остается плавающей. В вашем конкретном случае получилось, что результат был немного больше, чем ожидалось, поэтому приведение к int привело к равенству, но для других чисел это могло бы случиться, что оно будет немного меньше ожидаемого, а литье в int не будет округлено он, но обрезает его, поэтому вы не можете использовать кастинг в качестве обходного пути. (В качестве примечания, лучшее решение, чем ваше, будет отличать от строки :), но все же отвратительный вариант.)

Если вам нужно работать с суммой денег, всегда используйте расширение BC Math .

Для округления с помощью BC Math вы можете использовать эту технику:

 $x = '211.9452'; $x = bcadd($x, '0.005', 2); 

Удачи,
Алинь

использование

 round() $float_val = 4.5; $float_val = round($float_val); 

сейчас Сравнить

Например, неприятный случай: мы хотим проверить, больше ли наша оценка больше или равна 3,3 из 5, находясь в цикле. (Это все странный пример, чтобы показать «недостаток»)

 $a="3.3"; for($i=0; $i<5 ; $i=$i+0.15){ echo "\nTesting if $i>=$a\n"; var_dump($i,$a); if($i>=$a){ echo "$i>=$a is TRUE\n"; }else{ echo "$i>=$a is FALSE\n"; } } 

Теперь выход будет следующим:

 Testing if 0>=3.3 int(0) string(3) "3.3" 0>=3.3 is FALSE Testing if 0.15>=3.3 float(0.15) string(3) "3.3" 0.15>=3.3 is FALSE Testing if 0.3>=3.3 float(0.3) string(3) "3.3" 0.3>=3.3 is FALSE Testing if 0.45>=3.3 float(0.45) string(3) "3.3" 0.45>=3.3 is FALSE Testing if 0.6>=3.3 float(0.6) string(3) "3.3" 0.6>=3.3 is FALSE Testing if 0.75>=3.3 float(0.75) string(3) "3.3" 0.75>=3.3 is FALSE Testing if 0.9>=3.3 float(0.9) string(3) "3.3" 0.9>=3.3 is FALSE Testing if 1.05>=3.3 float(1.05) string(3) "3.3" 1.05>=3.3 is FALSE Testing if 1.2>=3.3 float(1.2) string(3) "3.3" 1.2>=3.3 is FALSE Testing if 1.35>=3.3 float(1.35) string(3) "3.3" 1.35>=3.3 is FALSE Testing if 1.5>=3.3 float(1.5) string(3) "3.3" 1.5>=3.3 is FALSE Testing if 1.65>=3.3 float(1.65) string(3) "3.3" 1.65>=3.3 is FALSE Testing if 1.8>=3.3 float(1.8) string(3) "3.3" 1.8>=3.3 is FALSE Testing if 1.95>=3.3 float(1.95) string(3) "3.3" 1.95>=3.3 is FALSE Testing if 2.1>=3.3 float(2.1) string(3) "3.3" 2.1>=3.3 is FALSE Testing if 2.25>=3.3 float(2.25) string(3) "3.3" 2.25>=3.3 is FALSE Testing if 2.4>=3.3 float(2.4) string(3) "3.3" 2.4>=3.3 is FALSE Testing if 2.55>=3.3 float(2.55) string(3) "3.3" 2.55>=3.3 is FALSE Testing if 2.7>=3.3 float(2.7) string(3) "3.3" 2.7>=3.3 is FALSE Testing if 2.85>=3.3 float(2.85) string(3) "3.3" 2.85>=3.3 is FALSE Testing if 3>=3.3 float(3) string(3) "3.3" 3>=3.3 is FALSE Testing if 3.15>=3.3 float(3.15) string(3) "3.3" 3.15>=3.3 is FALSE Testing if 3.3>=3.3 float(3.3) string(3) "3.3" 3.3>=3.3 is FALSE Testing if 3.45>=3.3 float(3.45) string(3) "3.3" 3.45>=3.3 is TRUE Testing if 3.6>=3.3 float(3.6) string(3) "3.3" 3.6>=3.3 is TRUE Testing if 3.75>=3.3 float(3.75) string(3) "3.3" 3.75>=3.3 is TRUE Testing if 3.9>=3.3 float(3.9) string(3) "3.3" 3.9>=3.3 is TRUE Testing if 4.05>=3.3 float(4.05) string(3) "3.3" 4.05>=3.3 is TRUE Testing if 4.2>=3.3 float(4.2) string(3) "3.3" 4.2>=3.3 is TRUE Testing if 4.35>=3.3 float(4.35) string(3) "3.3" 4.35>=3.3 is TRUE Testing if 4.5>=3.3 float(4.5) string(3) "3.3" 4.5>=3.3 is TRUE Testing if 4.65>=3.3 float(4.65) string(3) "3.3" 4.65>=3.3 is TRUE Testing if 4.8>=3.3 float(4.8) string(3) "3.3" 4.8>=3.3 is TRUE Testing if 4.95>=3.3 float(4.95) string(3) "3.3" 4.95>=3.3 is TRUE 

И отвратительная часть:

  Testing if 3.3>=3.3 float(3.3) string(3) "3.3" 3.3>=3.3 is FALSE 

3.3 больше или равно 3.3, но php вещи нет! Не имеет никакого смысла

Теперь, если вы положили ini_set('precision', 18); перед кодом вы можете видеть, что оценка на самом деле была:

 Testing if 3.29999999999999893>=3.3 float(3.29999999999999893) string(3) "3.3" 3.29999999999999893>=3.3 is FALSE 

Таким образом, $ i = $ i + = 0,15 неявно преобразует $ i в float , что вызовет эту проблему.

Для этого случая $ i + = 0,15 следует изменить на $ i = number_format ($ i + = 0,15, 2)