- Поисковые системы
- Практика оптимизации
- Трафик для сайтов
- Монетизация сайтов
- Сайтостроение
- Социальный Маркетинг
- Общение профессионалов
- Биржа и продажа
- Финансовые объявления
- Работа на постоянной основе
- Сайты - покупка, продажа
- Соцсети: страницы, группы, приложения
- Сайты без доменов
- Трафик, тизерная и баннерная реклама
- Продажа, оценка, регистрация доменов
- Ссылки - обмен, покупка, продажа
- Программы и скрипты
- Размещение статей
- Инфопродукты
- Прочие цифровые товары
- Работа и услуги для вебмастера
- Оптимизация, продвижение и аудит
- Ведение рекламных кампаний
- Услуги в области SMM
- Программирование
- Администрирование серверов и сайтов
- Прокси, ВПН, анонимайзеры, IP
- Платное обучение, вебинары
- Регистрация в каталогах
- Копирайтинг, переводы
- Дизайн
- Usability: консультации и аудит
- Изготовление сайтов
- Наполнение сайтов
- Прочие услуги
- Не про работу

Маркетинг для шоколадной фабрики. На 34% выше средний чек
Через устранение узких мест
Оксана Мамчуева

В 2023 году Google заблокировал более 170 млн фальшивых отзывов на Картах
Это на 45% больше, чем в 2022 году
Оксана Мамчуева
Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий
Всем доброго времени суток. Сегодня столкнулся со странной проблемой.
Очень подробно:
1. Достаю из базы 3 числа из одной и той же записи в таблице
нужно_забрать_яблок 5.4
яблок_на_складе 3.25
яблок_в_наличии 2.15
2. Далее вычисляю сколько и где нужно забрать яблок, так как на складе яблок меньше чем нужно, то "забираю_со_склада"="яблок_на_складе" (3.25), и вычисляю сколько забрать "забрать_из_яблок_в_наличии" = 5.4-3.25=2.15, потом примерно такой запрос в базу:
Делаю запрос:
@mysql_query("UPDATE `".$apple_table."` SET
`apple_stock`='".($res_balance['apple_stock']-$withdraw_apple_stock)."', //3.25-3.25 =0
`apple_stock_eat`='".($res_balance['apple_stock_eat']+$withdraw_apple_stock)."', //0+3.25 = 3.25
`apple_balance`='".($res_balance['apple_balance']-$withdraw_apple_balance)."', //2.15-2.15 = -4.4408920985006E-16
`apple_balance_eat`='".($res_balance['apple_balance_eat']+$withdraw_apple_balance)."' //0+2.15 = 2.15
...
WHERE `driver`='777'
",$db);
В итоге такие результаты:
`apple_stock`=0
`apple_stock_eat`=3.25
`apple_balance`= -4.4408920985006E-16 //должно быть 0
`apple_balance_eat`=2.15
И вот в двух словах:
Получается одно и тоже число при минусовании коряво считается (в квадратных скобках, число которое "лагает" и было достато из базы):
2.25-[2.25]=-4.4408920985006E-16
0+[2.25]=2.25
Кстати если вместо него ввести вручную 2.25 в туже переменную, то всё работает норм, также с некоторыми другими цифрами всё работает норм. Думал может число коряво было записано в базе, но 40 попыток его туда впихнуть по разному приводят всёравно к такому корявому результату..
Слышал про стандарт php IEEE 754 и про проблемы с сравниванием и вычислением чисел с павающей точкой (float), но ответ как решить вопрос так и не нашел, ну и тут при замене числа на такое же не из базы - всё работает норм.
В чём фокус?? Вообще ещё помню не раз замечал как "по дороге" переменные забывают что в них находится, особенном при частом их использовании..
Как это пофиксить можно? Пробывал и floatval([2.25]) и далее делал echo и выводило 2.25 и в этомже echo минусовал 2.25-[2.25]=-4.4408920985006E-16, также пробывал if([2.25]==2.25) - такое условие не срабатывает.
P.S 7 часов сижу в этом ковыряюсь :popcorn:
Слышал про стандарт php IEEE 754 и про проблемы с сравниванием и вычислением чисел с павающей точкой (float), но ответ как решить вопрос так и не нашел, ну и тут при замене числа на такое же не из базы - всё работает норм.
Числа float (с плавающей точкой) надо
сравнивать с допустимой погрешностью.
Как это пофиксить можно? Пробывал и floatval([2.25]) и далее делал echo и выводило 2.25 и в этомже echo минусовал 2.25-[2.25]=-4.4408920985006E-16, также пробывал if([2.25]==2.25) - такое условие не срабатывает. P.S 7 часов сижу в этом ковыряюсь 🍿
Для обязательной точности бухгалтерских
вычислений есть специальные библиотеки
для вычислений с десятичными дробями.
Там есть типы переменных,
функции, и дальше по списку.
Или используйте язык для бухгалтеров,
в котором уже есть такие вычисления.
https://en.wikipedia.org/wiki/COBOL
COBOL is a compiled English-like
computer programming language
designed for business use.
Тип данных в таблице - небось float? Яблоки с точностью до 38 знаков после запятой вешаете? :) Меняйте на decimal(15,3), читайте про float.
Тип данных в таблице - небось float? Яблоки с точностью до 38 знаков после запятой вешаете? :) Меняйте на decimal(15,3), читайте про float.
Да я в ручную в базу пихал число 2.5 и 3.5 и 5.4, далее 5.4-3.5=2.5 и вот потом начались нюансы уже с этим "вычисленным" 2.5.
Вообще да, в базе float везде у меня. Поставил тип полей DECIMAL, теперь там дробные числа не сохраняются.. Ааааа, вот заметил прикол, при создании DECIMAL там было 10,0 формат, погуглил немного и поменял на 19,2
И о чудо, в базу всё записалось как надо, а вот на экран вывел результат "вычисления" из переменной и получилось -4.4408920985006E-16
Я так понял главное чтоб в базе норм было, а то что оно там в переменной коряво хранится эт можно забить болт на это?? В целом доволен, спасибо.
---------- Добавлено 30.06.2016 в 04:53 ----------
Числа float (с плавающей точкой) надо
сравнивать с допустимой погрешностью.
Для обязательной точности бухгалтерских
вычислений есть специальные библиотеки
для вычислений с десятичными дробями.
Там есть типы переменных,
функции, и дальше по списку.
Или используйте язык для бухгалтеров,
в котором уже есть такие вычисления.
https://en.wikipedia.org/wiki/COBOL
COBOL is a compiled English-like
computer programming language
designed for business use.
И как с допустимой погрешностью сравнить если 2.25==2.25 не работает? Этож элементарные числа вроде как..
Калькулятор же на компе работает норм? Та и в инете куча сайтов где реальные вычисления есть и всё без проблем..
Этож элементарные числа вроде как.
Если для десятичных дробей использовать
приближение двоичными дробями, то обязательно
будут погрешности вычисления и представления,
потому что десять не есть степень двойки.
Тип float есть двоичная дробь, поэтому он
не может точно представлять десятичные дроби.
Для точных десятичных вычислений
нужны специальные типы данных.
Если для десятичных дробей использовать
приближение двоичными дробями, то обязательно
будут погрешности вычисления и представления,
потому что десять не есть степень двойки.
Тип float есть двоичная дробь, поэтому он
не может точно представлять десятичные дроби.
Для точных десятичных вычислений
нужны специальные типы данных.
Ну теперь буду знать, спасибо. Если честно до этого не было надобности в точных подсчётах, возможно не замечал эти косяки.. В целом если юзать в базе DECIMAL с настройкой (19,2), то числа типа -4.4408920985006E-16 нормально сохраняются, получается если вывести на экран то что в переменной, то будет фигня, а вот в базу сохранилось как мне нужно 2.15
Уже в базе заменил все типа данных с FLOAT на DECIMAL, так что думаю норм будет.
Всем огромное спасибо. Реально 10 часов сидел ковырял это дело, мозг отключился. Всем добра и удачи!
Для финансовых (денежных) операций, лучше хранить в decimal(16,4), чтоб вдруг не потерять на конвертации валют
Но и там есть нюансы, которые редко учитывают
при сложении, умножении, округлении - могут теряться копейки
при сложении, умножении, округлении - могут теряться копейки
Поэтому в финансовых системах деньги хранят в целых числах (в копейках) т.е., чтоб не терялись ;)
0,001
*
100
=
0,1
Верно
Но цены 0,001 не существует, и предстаалена в виде 0,01
0,01
*
100
=
1.00
О! Как надо работать!
Для финансовых (денежных) операций, лучше хранить в decimal(16,4), чтоб вдруг не потерять на конвертации валют
Но и там есть нюансы, которые редко учитывают
при сложении, умножении, округлении - могут теряться копейки
Да мне всё что ниже сотых 0.01 - не нужно, я и так округляю в меньшую сторону)
Так что остановился на формате decimal(19,2)
Ещё мучал вопрос что за число -4.4408920985006E-16, оказывается это число 0, надеюсь с нормальными числами которые больше нуля - таких нюансов не будет..
Кстати вопрос, а если у меня при вычислениях вместо 7.77 выйдет число типа NaN, то при сохранение в базу оно сохранится нормально?
Храни в целых числах [x], показывай как хочешь - [x] / 100(1000, 10000)...
А версия mysql какая?
Тут неплохо разжевано все
http://tarlyun.com/blog/2011/03/22/xranenie-ne-celyx-chisel-v-mysql/