[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Неверный результат сравнения переменных в if
ILL-JAH
Всем привет.
Написал небольшой скриптик. Задачка по матиматике с генерацией значений в условии.
Пользователь должен решить задачку, ввести свой вариант ответа в текстовое поле и нажать на кнопку "ответить".
Правильный ответ лежит в переменной $change. Ответ пользователя - в переменной $input.
При сравнении переменных, содержащих дробные значения, в if($change == $input) скрипт ПОЧТИ всегда выдаёт "ответ неверный". Даже если пользователь правильно решил задачу и ввёл правильный ответ. Однако если тип $change изменить на string, а потом на double, то if($change == $input) работает корректно.
В случае если ответ - целое число, всё работает правильно.
Люди добрые и более опытные чем я, объясните пожалуйста, почему так происходит? Почему 2 одинаковых числа с одинаковым типом double при сравнении в if дают false и ветвление сваливается в else?


<?php
if($_SERVER["REQUEST_METHOD"] == "GET") {
$kg1 = rand(1, 99); //стоимость 1 кг. огурцов (от 1р до 99р)
$bought = rand(1, 99)/10; //куплено кг огурцов (от 0,1 кг до 9,9 кг)
//Потраченных денег: min 0,1 руб. max 980,1 руб.

$moneySpent = $bought*$kg1; //стоимость купленных огурцов
$cash = ceil($moneySpent); //избавляемся от копеек
settype($cash, "string");
$first = $cash{0};
settype($first, "int");
$first++;
$realCash = $first*pow(10, strlen($cash)-1);
$change = $realCash-$moneySpent; //сдача
//$message = "$change";

$message = "";
}
if($_SERVER["REQUEST_METHOD"] == "POST") {
$kg1 = $_POST["kg1"];
$bought = $_POST["bought"];
$realCash = $_POST["realCash"];
$input = $_POST["input"];
if(preg_match("/,/", $input)) $input = preg_replace("/,/", '.', $input);

settype($kg1, "double");
settype($bought, "double");
settype($realCash, "int");
$moneySpent = $bought*$kg1;
$change = $realCash-$moneySpent;
settype($change, "string"); //пришлось преобразовывать double->string->double. Без него какого-то хрена $change != $input
settype($change, "double");
settype($input, "double");
if($change == $input) {
//$message = $change."ответ верный".$input;
$message = "ответ верный";
} else {
//$message = $change."ответ неверный".$input."".gettype($change)." ".gettype($input);
$message = "ответ неверный";
}
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>
Задача №1</title>
</head>
<body>
<div>
<form
action="<?=$_SERVER['SCRIPT_NAME']?>" method="post">
<div>
<p>
Задача №1.<br />Один килограмм огурцов стоит <?=$kg1?> рублей. Мама купила <?=$bought?> кг. огурцов.<br />
Сколько рублей сдачи она должна получить, заплатив <?=$realCash?> рублей.</p>
<input
type="text" name="input" />
<input
type="submit" name="sendAnswer" value="ответить" />
<input
type="hidden" name="kg1" value="<?=$kg1?>"/>
<input
type="hidden" name="bought" value="<?=$bought?>"/>
<input
type="hidden" name="realCash" value="<?=$realCash?>"/>
<br /><br /><br />
<a
href="diag0_1.php">Попытаться решить задачу №1 с новыми условиями</a><br />
<a
href="diag0.htm">Вернуться в меню выбора задач диагностической работы №0</a><br />
<a
href="B1.htm">Вернуться в меню выбора работ тетради B1</a><br />
<a
href="menu.htm">Вернуться в меню выбора рабочих тетрадей</a>
<br /><br /><br />
<p><?=
$message?></p>
</div>
</form>
</div>
</body>
</html>




Спустя 28 минут, 20 секунд (20.08.2012 - 17:08) Игорь_Vasinsky написал(а):
ну наверно нужно ловить и сравнивать float и если юзер ввёл цифру с запятой - то для сравнения её нужно заменить на точку.

Спустя 1 минута, 35 секунд (20.08.2012 - 17:09) Игорь_Vasinsky написал(а):
и потом - юзер может скока угодно ввести цифр после точки - это тоже нужно предусмотреть, так как 4.09 != 4.091

значит - нужно брать только нужное кол-во символов.

Спустя 1 час, 50 минут, 55 секунд (20.08.2012 - 19:00) ILL-JAH написал(а):
Цитата (Игорь_Vasinsky @ 20.08.2012 - 15:08)
ну наверно нужно ловить и сравнивать float

В РНР есть разница между float и double?
Цитата (Игорь_Vasinsky @ 20.08.2012 - 15:08)
если юзер ввёл цифру с запятой - то для сравнения её нужно заменить на точку.

Строка
if(preg_match("/,/", $input)) $input = preg_replace("/,/", '.', $input);

как раз и решает эту проблему.

Спустя 15 минут, 2 секунды (20.08.2012 - 19:15) ILL-JAH написал(а):
Цитата (Игорь_Vasinsky @ 20.08.2012 - 15:09)
и потом - юзер может скока угодно ввести цифр после точки - это тоже нужно предусмотреть, так как 4.09 != 4.091

значит - нужно брать только нужное кол-во символов.

Скрипту всё ровно, что там вводит юзер. Уникальные условия задачи, генерируемые скриптом при каждом новом вызове страницы, таковы, что задача имеет каждый раз только один единственный вариант ответа. И если этот ответ 4.09, то и 4.091 и 4.089 и другие варианты - это неправильные ответы. И скрипт здесь отрабатывает абсолютно корректно, выводя сообшение "ответ неверный". Проблема в том, что когда пользователь вводит правильный ответ, то оператор if в своём условии всё ровно возвращает false и выводится сообщение "ответ неверный".

Спустя 2 часа, 24 минуты, 48 секунд (20.08.2012 - 21:40) inpost написал(а):
http://php.net/manual/ru/language.types.float.php
Цитата: "Так что никогда не доверяйте точности чисел с плавающей точкой до последней цифры, и не проверяйте напрямую их равенство. "

Спустя 50 минут, 12 секунд (20.08.2012 - 22:30) ILL-JAH написал(а):
inpost, пасиб. Вопрос исчерпан.
з.ы. Удивлён. Ответы на задачку могут иметь только 1 знак после запятой.

Спустя 28 минут, 3 секунды (20.08.2012 - 22:58) inpost написал(а):
Можешь вообще легко сделать, передаётся не float, а string, его разбей по разделителю и сравнивай уже отдельно smile.gif Но мне кажется, что это неверно тоже.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.