Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Округляшка дает сбой, INT выдает странный результат 
:(
    Опции темы
MaxPayne
Дата 24.11.2014, 00:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Столкнулся с удивительной штукой в интернет магазине, который я делал на PERL. 

Идет обсчет цены с учетом скидки - все ок. Но сегодня прошла цена 1890 и случилось нечто. PERL обсчитал 0% скидку и выдал цену 1880 (т.е. скидка в 10 рублей). Это мелочи, но хочется узнать в чем проблема. Тестировал с другими ценами - все ок.

Подскажите...

Формула такая: $summafullskidka = (int((($summa/100)*(100-$skidka))/10))*10;
Соответственно SUMMA = 1890, SKIDKA =0.
НА ВЫХОДЕ $summafullskidka = 1880

ИСКАЛ НА КАКОМ ЭТАПЕ И РАЗБИЛ НА ЧАСТИ:
В КОНЦЕ КАЖДОЙ СТРОКИ РЕЗУЛЬТАТЫ
###
$summa11 = $summa/100; 18.9
$summa22 = 100-$skidka;         100
$summa33 = $summa11*$summa22; 1890
$summa44 = $summa33/10; 189
$summa55 = (int($summa44)); 188
$summa66 = $summa55*10; 1880
###

Подключены только два модуля 
use CGI qw(:all);
use DBI;


Это сообщение отредактировал(а) MaxPayne - 24.11.2014, 00:37
PM MAIL WWW ICQ   Вверх
igorold
Дата 24.11.2014, 07:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 557
Регистрация: 22.12.2005
Где: Россия->Урал-& gt;Миасс

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



Посмотри результат:

Код

my $rez = sprintf("%.20f",$summa)." ".sprintf("%.20f",$summa/100)."\n";
print $rez;



ну сделай проверку на условие $skidka = 0 или нет.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
Bulat
Дата 24.11.2014, 08:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


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

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



Цитата(MaxPayne @  24.11.2014,  00:36 Найти цитируемый пост)
$summa55 = (int($summa44));

Я так понимаю, что в это строке ты пытаешься округлить до целого числа. Только int

Цитата

    int     Returns the integer portion of EXPR. If EXPR is omitted, uses
            $_. You should not use this function for rounding: one because
            it truncates towards 0, and two because machine representations
            of floating-point numbers can sometimes produce counterintuitive
            results. For example, "int(-6.725/0.025)" produces -268 rather
            than the correct -269; that's because it's really more like
            -268.99999999999994315658 instead. Usually, the "sprintf",
            "printf", or the "POSIX::floor" and "POSIX::ceil" functions will
            serve you better than will int().


из перлдока You should not use this function for rounding. ну и далее все описано подробно.

Если нужно именно округление - как вариант

Код

use POSIX qw /ceil/;

....
$summa55 = POSIX::ceil($summa44);
....



--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
MaxPayne
Дата 24.11.2014, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(igorold @ 24.11.2014,  08:23)
Посмотри результат:

Код

my $rez = sprintf("%.20f",$summa)." ".sprintf("%.20f",$summa/100)."\n";
print $rez;



ну сделай проверку на условие $skidka = 0 или нет.

Этот ответ добавлен с нового Винграда - http://vingrad.com

Скидка ИМЕННО 0.
PM MAIL WWW ICQ   Вверх
tzirechnoy
Дата 24.11.2014, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Учитывая натуру перла (динамическая типизацыя, автоматические преобразования, машынные типы) -- я бы посоветовал для рассчёта денег взять Math::BigInt. Очень удобно -- значение всегда int, безо всяких альтэрнатив.

То есть этот случай -- банален, конечно (если нет -- то тем более возьмите Math::BigInt), но он наглядно показывает -- что бывает если floating point использовать с деньгами. Ничего хорошэго. Дажэ если для промежуточных результатов рассчётов.
PM MAIL   Вверх
MaxPayne
Дата 24.11.2014, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Поставил POSIX::ceil.

Странно, я бы понял такое округление когда число было бы десятичным - типа 189.433234.

А тут то целое число от 189 = 188.

Не ожидал я такого от INT.
PM MAIL WWW ICQ   Вверх
tzirechnoy
Дата 24.11.2014, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



1890/10 -- не будет цэлым числом. Поскольку цэлочисленного деления в perl вообще не предусмотрено.

Добавлено через 5 минут и 28 секунд
Да, про POSIX::ceil -- это, честно говоря, редкостный FAIL.

Вы вообще не поняли, что произошло и что Вы сделали. Совсем. Я мог бы подсказать код, который делает правильно в данном конкретном случае -- но, истинно говорю вам, возьмите Math::BigInt и не используйте floating point для денег.
Вы вряд ли скоро поймёте, что такое floating point, что у него за проблемы округления, почему int() в perl сделали именно так, какое округление -- правильное, и, наконец, почему floating point не стоит использовать для денег. Просто поверьте на слово, и возьмите BigInt.
PM MAIL   Вверх
Bulat
Дата 24.11.2014, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


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

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



Цитата(MaxPayne @  24.11.2014,  17:04 Найти цитируемый пост)
Не ожидал я такого от INT. 

Скорее поленился прочитать документацию. А чтива там на две минуты и ответ на все вопросы!  smile

Добавлено через 3 минуты и 24 секунды
Цитата(MaxPayne @  24.11.2014,  17:04 Найти цитируемый пост)
А тут то целое число от 189 = 188.

P.S. В Perl нет целых чисел(нет определения типов подобно С).  smile  smile 


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
tzirechnoy
Дата 24.11.2014, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата
P.S. В Perl нет целых чисел(нет определения типов подобно С). 


Есть. Например, сравни:

Код
0_ilan@azor /tmp%perl -e 'print sprintf("%30d\n", 2**62+1)'   
           4611686018427387904
0_ilan@azor /tmp%perl -e 'print sprintf("%30d\n", int(2**62)+1)'
           4611686018427387905
0_ilan@azor /tmp%


Несмотря на то, что число 4611686018427387904 вроде бы одно и тожэ -- оно вполне представимо и в цэлочисленном и в виде IEEE754 double, мы видим разницу между цэлым 4611686018427387904 и 4611686018427387904 с плавающей точкой.

Но да, Ларри сделал многое, чтобы этих цэлых чисел было не видно и не слышно. По сути, действительно, можно сказать что цэлых чисел в перле нет -- есть только числа с плавающей точкой, всё остальное -- практически от них неотличимо.

Соответственно, использовать перловые числа для хранения денег -- нельзя. Используйте строки, BigInt или выкручивайтесь ещё как-то.
PM MAIL   Вверх
Bulat
Дата 24.11.2014, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


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

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



Цитата(tzirechnoy @  24.11.2014,  19:31 Найти цитируемый пост)

Есть. Например, сравни:

Это пустой холивар... который никому не нужен...

Цитата(tzirechnoy @  24.11.2014,  19:31 Найти цитируемый пост)
использовать перловые числа для хранения денег -- нельзя

Глупость какая... Все зависит от мастерства, таланта и квалификации программиста, а не от того какой язык или технология используется...


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
tzirechnoy
Дата 25.11.2014, 00:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата
Все зависит от мастерства, таланта и квалификации программиста,


Я таких умных, которые считают, что всё зависит от их мастерства, таланта и квалификацыи -- периодически на Новорижском вижу. Вокруг них ещё менты и мужыки с болгарками часто ошываются. И труповозка чуть поодаль.

Есть, знаете ли, некоторые простые и достаточно общепринятые правила. Ну там, не более 160 на нашых сраных дорогах (на лучшых из них), полторы секунды резерва, делать бэкапы, тренироваться восстанавливать бэкапы, не хранить деньги в флоатах.

Их можно несоблюдать. Штраф жызнь сама выпишэт.


PM MAIL   Вверх
Bulat
Дата 25.11.2014, 06:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


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

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



Цитата(tzirechnoy @  25.11.2014,  00:28 Найти цитируемый пост)
Я таких умных, которые считают, что всё зависит от их мастерства, таланта и квалификацыи -- периодически на Новорижском вижу. Вокруг них ещё менты и мужыки с болгарками часто ошываются. И труповозка чуть поодаль.

Пока что я тебя вижу - строящего из себя самого умного... 


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

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


 




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


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

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