Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Объясните в чем баг 
:(
    Опции темы
Leoo
Дата 14.8.2013, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 270
Регистрация: 3.10.2005
Где: г. Обнинск

Репутация: 1
Всего: 3



Код

$p1 = 1.4;
$p2 = 1.2;
if(2.6 == ($p1+$p2)) print 'true';
else print 'false';


почему данное выражение выдает false


--------------------
Если вы не страдаете паранойей, это не значит, что они за вами не летят!
PM MAIL WWW ICQ   Вверх
Fortop
Дата 14.8.2013, 19:32 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(Leoo @  14.8.2013,  16:52 Найти цитируемый пост)
почему данное выражение выдает false 

Потому что числа с плавающей точкой сравнивать на равенство бесполезно
Будут округления.

Правильнее сравнивать на диапазон точности

value - delta < calculatedValue < value + delta

Где delta это требуемая тебе точность
А value это собственно значение с которым ты сравниваешь.


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Arantir
Дата 14.8.2013, 20:25 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 16
Всего: 55



Наглядно:
Код

$f1 = 1.2 + 1.4;
$f2 = 2.6;
echo base_convert(unpack('H*', pack('d', $f1))[1], 16, 2), "\n";
echo base_convert(unpack('H*', pack('d', $f2))[1], 16, 2), "\n";


Цитата
1100110011001100110011001100110011001100110011000000000000000000
1100110111001100110011001100110011001100110011000000000000000000


Это сообщение отредактировал(а) Arantir - 14.8.2013, 20:28


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Cript777
  Дата 14.8.2013, 23:28 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 82
Регистрация: 30.10.2012

Репутация: нет
Всего: нет



Цитата(Leoo @ 14.8.2013,  16:52)
Код

$p1 = 1.4;
$p2 = 1.2;
if(2.6 == ($p1+$p2)) print 'true';
else print 'false';


почему данное выражение выдает false

А ты вот так попробуй.. У меня лично true выдает. 
Код

<?
$p1 = '1.4';
$p2 = '1.2';
$p3 = $p1+$p2;
if(2.6 == "$p3") 
{ print 'true'; }
else { print 'false'; }
?>


Это сообщение отредактировал(а) Cript777 - 14.8.2013, 23:31
PM MAIL   Вверх
Arantir
Дата 15.8.2013, 02:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 16
Всего: 55



А слово "float" всегда обозначает одну и ту же технологию хранения и арифметических операций. Соответсвенно, float всегда означает неточность, которая исходит из самого принципа его работы.
Во многих других языках класс для точных вычислений является встроенным и поддерживается на уровне языка. Такой класс/тип данных принято называть Decimal.
PHP в первую очередь создан для выдачи динамически сформированного HTML-кода браузеру... Собственно, об этом говорит сама аббревиатура "PHP".


Так что, если эта тема была создана для решения некой проблемы, а не только из-за непреодолимой жажды к познанию, пониманию и осознанию, то:

Для бытовых потребностей:
Код

$precision = 1;
$p1 = 1.4;
$p2 = 1.2;
if(2.6 == round($p1+$p2, $precision)) // round спешит на помощь
    print 'true';
else 
    print 'false';
Результаты у round всегда одинаковы. 2.6 - значит 2.6. Достаточно округлять все числа перед сравнением.

Для научных (точных) вычислений: http://www.php.net/manual/ru/ref.bc.php
Поддержки на уровне языка нет. Но есть библиотечка с функциями. Работает со строками. Впрочем, это не проблема с динамической-то типизацией.


Это сообщение отредактировал(а) Arantir - 15.8.2013, 02:13


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Leoo
Дата 15.8.2013, 07:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 270
Регистрация: 3.10.2005
Где: г. Обнинск

Репутация: 1
Всего: 3



просто эта проблема проявляется только для $p1 = 2 или 3, $p2 = 4 или 6 и чтоб полученные результат был 6 или 9, причем все равно какое целое число впереди, главное чтоб десятые были такими.
но если $p1 будет равно 1.1 или какому нибудь другому числу, то результат уже тру
т.е прослеживается две последовательности (2,4,6) или (3,6,9)
если эти числа будут в сотых, то опять же результат будет тру

работу проверил на 5 разных машинах и с виндой и с убунтой и с макосью

способ как ее решить тоже нашел, просто очень интересно в чем секрет.


--------------------
Если вы не страдаете паранойей, это не значит, что они за вами не летят!
PM MAIL WWW ICQ   Вверх
Arantir
Дата 15.8.2013, 12:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 16
Всего: 55



Leoo, есть такое понятие - бесконечные дроби... 
Так вот, в двоичной системе оно тоже есть. Но вот загвоздка в том, что в двоичной и десятичной это не одни и те же числа. Да и вообще в двоичной конечных дробей поменьше. 
То что для человека 0.3, для компьютера — что-то вроде 001111101.001100110011001100110011... А в обратную сторону это уже не 0.3, "почти 0.3". 
Суть та же, что для записей чисел 1/3 и 0,33333333333333333333333333333333.

Многие числа изначально неточны:
Код

$p1 = 1.2;
$p2 = 1.4;
$p3 = 2.6;
printf("%.100e", $p3);
printf("%.100e", $p1);
printf("%.100e", $p1);
printf("%.100e", $p2);
printf("%.100e", $p1+$p2);
Код
2.60000000000000008881784197001252323389053344726562500e+0
1.19999999999999995559107901499373838305473327636718750e+0
1.19999999999999995559107901499373838305473327636718750e+0
1.39999999999999991118215802998747676610946655273437500e+0
2.59999999999999964472863211994990706443786621093750000e+0


Числа в двоичном виде - это суммы степеней двойки. В том числе степеней отрицательных (нолики и единички после запятой). Точно могут быть представлены только числа, являющиеся суммой 0.5, 0.25, 0.125, 0.0625 и так далее...
Код

$p0 = 0.125;
$p1 = 0.5;
$p2 = 0.625;
$p3 = 0.5625;
printf("%.100e", $p0);
printf("%.100e", $p1);
printf("%.100e", $p2);
printf("%.100e", $p3);
printf("%.100e", $p0+$p1);
printf("%.100e", $p1+$p2);
printf("%.100e", $p2+$p3);
Код
1.25000000000000000000000000000000000000000000000000000e-1
5.00000000000000000000000000000000000000000000000000000e-1
6.25000000000000000000000000000000000000000000000000000e-1
5.62500000000000000000000000000000000000000000000000000e-1
6.25000000000000000000000000000000000000000000000000000e-1
1.12500000000000000000000000000000000000000000000000000e+0
1.18750000000000000000000000000000000000000000000000000e+0


Представьте, что Вы с компьютером поменялись местами. У вас есть карандаш и узкий длинный листок бумаги. Записывать числа вы умеете только в виде десятичных дробей и ограниченной длины. А отвечать Вы должны с некой заданной точностью, например, 16 знаков. Вас просят сложить числа 1/3 и 2/3
Вы их превращаете в дроби и складываете
0,66666666666666666666666666666666
0,33333333333333333333333333333333
получаете
0,99999999999999999999999999999999
Вы берете 17 знак и округляете. Получается ровно 1.
А потом вас просят сравнить (1/3 + 2/3) и 1
Вы сравниваете
0,99999999999999999999999999999999
1,00000000000000000000000000000000
и выдаете "НЕ РАВНО".


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0708 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.