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

Поиск:

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


Unregistered











Без долгих рассуждений - есть код:
Код

#!c:/perl/bin/perl.exe
use strict;

my %P;
$P{'Первый Множитель'} = 120.3; 
$P{'Второй Множитель'} = 7300;
$P{'Tретий Множитель'} = 1.050;
$P{'Четвертый Множитель'} = 1.030;
$P{'Произведение по первой схеме'} = $P{'Первый Множитель'} * $P{'Второй Множитель'} * $P{'Tретий Множитель'} * $P{'Четвертый Множитель'};
$P{'Произведение по второй схеме'} = $P{'Tретий Множитель'} * $P{'Четвертый Множитель'} * $P{'Первый Множитель'} * $P{'Второй Множитель'};

printf "Произведение по первой схеме неокругленное: %.20f\n", $P{'Произведение по первой схеме'};
printf "Произведение по первой схеме округленное: %.2f\n", $P{'Произведение по первой схеме'};
printf "Произведение по второй схеме неокругленное: %.20f\n", $P{'Произведение по второй схеме'};
printf "Произведение по второй схеме округленное: %.2f\n", $P{'Произведение по второй схеме'};


Насколько я помню математику 4-го класса, от перемены мест множителей произведение не меняется. Данный скрипт иллюстрирует, что у перла на это свое мнение. smile
(результат работы приведенного выше скрипта)
Цитата

Произведение по первой схеме неокругленное: 949762.48499999999000000000
Произведение по первой схеме округленное: 949762.48
Произведение по второй схеме неокругленное: 949762.48500000010000000000
Произведение по второй схеме округленное: 949762.49


Я понимаю, что проблемма связана с представлением чисел с плавающей запятой в компьютере. Но все же, что же делать то?
Есть идеи?
  Вверх
Kiber_rat
Дата 25.11.2005, 01:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MACMANIAC
**


Профиль
Группа: Участник
Сообщений: 276
Регистрация: 18.4.2002
Где: Ashdod, Israel

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



Я бы попробовал заюзать какой нить математический модуль... Math::Big к примеру. А по простому - используй целочисленную математику., т.е. перед тем как использовать операнды, умножь их на 10000 (что бы все стали целыми) а потом результат - раздели на те же 10000 smile

Это сообщение отредактировал(а) Kiber_rat - 25.11.2005, 01:52


--------------------
Best regards!                                                             
@..@_____Ku6ep
=*=______\______KPbIC
Код
print join "",map{chr}(split/(\w{2})/,hex(int(2175.57302796298**2)))
PM WWW ICQ Skype Jabber YIM   Вверх
Uhuhu
Дата 25.11.2005, 20:17 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Перл округляет числа не по привычной математической схеме (до пяти сотых - меньше, после - больше), а по привычной для программистов схеме (и более удобной?): к четному числу.

Читайте спецификацию языка

  Вверх
wladk
Дата 26.11.2005, 01:19 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата(Uhuhu @ 25.11.2005, 20:17)
Перл округляет числа не по привычной математической схеме (до пяти сотых - меньше, после - больше), а по привычной для программистов схеме (и более удобной?): к четному числу.

1. Для програмиста много чего привычно и удобноsmile Однако же есть еще в мире случаи, когда программисты пишут программы для кого-то, кто не есть программист. Например бухгалтер. А их(вот же людей затуркали) убедили, что 1,245 после округления будет 1,25, а не 1,24... smile
2, Если вы внимательно посмотрите на данные, то увидите, что в одном случае округлестя к четному 949762.48, а другой раз к не четному 949762.48. Вот в эотом то был вопрос.... в зависимости результат от порядка следования операндов...

Цитата

Читайте спецификацию языка


ссылочку будьте добры. А то у меня в башку вот засело, хоть ты тресни
Цитата
Peri округляет последний разряд вверх, если следующая цифра равна 5 и более, и вниз в противном случае.

Что в принципе соотносится с данными в предидущем примере....
А вы случайно не спутали с функцией Round, модуля Math::BigFloat, вот у нее таки да, такой характер....
  Вверх
Guest
Дата 26.11.2005, 01:23 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Цитата(Kiber_rat @ 25.11.2005, 01:17)
Я бы попробовал заюзать какой нить математический модуль... Math::Big  к примеру. А по простому - используй целочисленную математику., т.е. перед тем как использовать операнды, умножь их на 10000 (что бы все стали целыми) а потом результат - раздели на те же 10000 smile


Спасибо за идею.... ВОт идея с челочисленной математикой мне понравилась... Только наверное и хранить так надо.... а при выводе делить. Только не 10000, а на кол-во множителей*10000:)

А моножителей может быть дофигища......
Все равно спасибо! Вывел меня из ступора!:)))
  Вверх
Usya
Дата 26.11.2005, 06:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата
Я понимаю, что проблемма связана с представлением чисел с плавающей запятой в компьютере. Но все же, что же делать то?


А что здесь поделаешь??? Ничего... Perl все правильно сделал. Я тебе могу кучу примеров привести, где от перестановки может координально поменяться ответ. Да и в учебниках есть соответствующие примеры об этом... И округлил Perl результаты правильно.

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

На счет идей - попробуй перед тем, как выводить результат в приведенном коде, прибавить к нему, например, 0.0000000001 - мелочь, а приятно. И будет Вам счастье smile . Хотя надо посмотреть, может придется на всякий случай прибавлять число, например, в 10 или 100 раз поболее (на всякий случай). Это зависит от количества и вида операций... Для хранения данных ничего прибавлять не надо.

P/s
Цитата
А моножителей может быть дофигища......
Все в мире относительно.
Почитай про абсолютную погрешность и ты сам сможешь ее оценить. А то может эта погрешность оказаться больше твоего результата со всеми вытекающими последствиями smile

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


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

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


 




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


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

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