Почему вдруг меняется тип переменной и содержание?

zerAlex

Новичок
Почему вдруг меняется тип переменной и содержание?

Все переменные вроде "sort1balance" - это целые числа или дробные.

PHP:
$final=(($sort1balance)+($sort2balance)+($sort3balance)+($sort4balance));
echo $final." = ( ($sort1balance) + ($sort2balance) + ($sort3balance) + ($sort4balance) )";
А выводит это:
-5.3290705182E-15 = ( (1.2) + (-1) + (0.7) + (-0.9) )

С какой стати это не равно нулю??? Я сконфужен.....
 

Luge

Нестандартное звание
Re: Почему вдруг меняется тип переменной и содержание?

Автор оригинала: http://www.php.net/manual/ru/language.types.float.php
Довольно часто простые десятичные дроби вроде 0.1 или 0.7 не могут быть преобразованы в свои внутренние двоичные аналоги без небольшой потери точности. Это может привести к неожиданным результатам: например, floor((0.1+0.7)*10) скорее всего возвратит 7 вместо ожидаемой 8 как результат внутреннего представления числа, являющегося в действительности чем-то вроде 7.9999999999....

Это связано с невозможностью точно выразить некоторые дроби в десятичной системе счисления конечным числом цифр. Например, 1/3 в десятичной форме принимает вид 0.3333333. . ..

Так что никогда не доверяйте точности последних цифр в результатах с числами с плавающей точкой и никогда не проверяйте их на равенство. Если вам действительно необходима высокая точность, вам следует использовать математические функции произвольной точности или gmp-функции.
 

zerAlex

Новичок
Один нюанс - у меня на входе числа максимум с 2-мя знаками после запятой и идет только сложение и вычитание.

Выходит, что не место числам типа 7,999999999999 в моих переменных.

Так что, вопрос остается :(

Еще момент - убираю из выражения любую переменную из четырех и никаких float нет. Глюк?
PHP:
$final=(($sort1balance)+($sort2balance)+($sort3balance));
echo $final."<br>";
$final+=($sort4balance);
echo $final."<br>";
$final=(($sort1balance)+($sort3balance)+($sort4balance));
echo $final."<br>";
$final+=($sort2balance);
echo $final."<br>";
Выводит:
0.9
-5.3290705182E-15
1
-5.3290705182E-15
 

Angerslave

Новичок
Ну как это float нет? У тебя там только -1 не float, всё остальное - дробные числа.
 

kstati

Новичок
Но в то же самое время
PHP:
floor((0.1*10+0.7*10));
оправдывает ожидание.

Если использование с точкой не принципиально (например допустимо писать вместо 1.5 руб -- 150 коп, вместо 0.16 -- 16%), то проблема решается отказом от чисел с точкой.

Иначе - если заранее известно количество знаков после запятой, можно сделать соответствующие поправки -- каждый операнд умножить на нужную степень десятки (чтобы все операнды были целочисленными), провести операцию (сложение, вычитание и т.п.) затем разделить результат на выбранную степень десятки.

PHP:
( (1.2*10) + (-1*10) + (0.7*10) + (-0.9*10) )/10 === 0


$sort1balance= 1.2;
$sort2balance= -1.0;
$sort3balance=0.7;
$sort4balance=-0.9; 

$final=(($sort1balance*10)+($sort2balance*10)+($sort3balance*10)+($sort4balance*10))/10; 
echo "result = ".$final;
result = 0

Ну, а если максимальное количество знаков после запятой не известно - то тогда уже остается использовать сторонние библиотеки, либо писать свои.
 

zerAlex

Новичок
Это проблема. Нужно переписывать туеву хучу кода, менять данные в базе...

Не понимаю. Все работает отлично. Проблема только с этой строкой. Причем в 2-х разных файлах эта формула выдает такую чушь... Причем только тогда, когда результат равен 0 !!!

floor дает -1 , а не 0 .
 

Beavis

Banned
zerAlex
Потому что при работе с дробными числами надо представлять что это такое...
Обычно с самого начала программистов учат что сравнивать флоаты нельзя друг с другом
 

zerAlex

Новичок
БОМБА!
Т.е. 0.1+0.7=0.799999999999

Вот это математика!!!

Ребят, еще раз напомню: нет умножения и деления. Есть только сложение и вычитание. Как это возможно с числами, где после запятой только 2 знака? Не укладывается. На примере, PLZ.
 

Angerslave

Новичок
zerAlex
Тебе лучше почитать как дробные числа в компьютерах хранятся.
 

korchasa

LIMB infected
Мантисы, допкод, плавающая точка(запятая), код Хемминга, и тетрадка на 18 листов с описанием одной операции деления. Ностальгия...
 

Beavis

Banned
Автор оригинала: korchasa
тетрадка на 18 листов с описанием одной операции деления.
Вы изучали поведение орбИт атомов в процессоре при делении чтоль?=))) Или ахулеард на ноль делили?=)
 

korchasa

LIMB infected
Автор оригинала: Beavis
Вы изучали поведение орбИт атомов в процессоре при делении чтоль?=))) Или ахулеард на ноль делили?=)
Нет, мы изучали математические операции, в том виде, в котором они происходят в железках)
Оказывается не так-то просто поделить числа с плавающей точкой, если единственные доступные операции - сложение и инверсия.
 

zerkms

TDD infected
Команда форума
Angerslave
сам же автор несколько раз в статье произносил термин "стремится", а в конце незатейливо перешёл к "равно"
"предел" и "равенство" это разные вещи

по ссылке на английском вообще странные вещи написаны

9.(9) - .(9) с лёгкой руки у него становится равным 9. пары вышки у меня были уже довольно давно, но нас всё таки учили, что так делать нельзя
 

Angerslave

Новичок
zerkms
Что стремится? Где там переменная? 0,(9) это число, оно никуда не стремится. И это предел. Предел, который равен 1. В комментах более доходчиво с разных сторон это всё описывается. Это какая-то там функция может стремиться к пределу, а 0,(9) в периоде это не функция, это и есть предел.
 
Сверху