ошибка вычислений при умножении на 0, проблема в whille

Форум пользователей пакета Mathcad

Модератор: Admin

КудяшоваГалина
Сообщения: 7
Зарегистрирован: Пн окт 19, 2015 7:11 pm

ошибка вычислений при умножении на 0, проблема в whille

Сообщение КудяшоваГалина » Ср окт 21, 2015 1:15 am

при вычислении простейших примеров, вылезли странные ошибки( кто встречался с таким?
Задача: вычислить произведение чисел от 1 до m с шагом 0.1.

При вычислении с использованием цикла while не всегда срабатывает условие <= (картинка f1). На картинке f2 правильное решение, но это обходной путь.

При вычислении произведения чисел от -m до 1 с шагом 0,1 по логике мы придем в ноль и все произведение должно быть равно 0. При увеличении m по модулю этого не происходит (картинка f3).

Заранее благодарю откликнувшимся.
Изображение
Изображение
Изображение

Nub
Сообщения: 35
Зарегистрирован: Пн май 06, 2013 11:46 am

Сообщение Nub » Ср окт 21, 2015 10:47 am

вещественные числа некорректно сравнивать по "=", мне это говорили на 1 курсе сразу
при любых операциях с ними накапливается погрешность - говорили тогда же :)

КудяшоваГалина
Сообщения: 7
Зарегистрирован: Пн окт 19, 2015 7:11 pm

Сообщение КудяшоваГалина » Ср окт 21, 2015 11:53 am

Nub писал(а):вещественные числа некорректно сравнивать по "=", мне это говорили на 1 курсе сразу
при любых операциях с ними накапливается погрешность - говорили тогда же :)


В Делфи таких проблем не было просто( спасибо. А что с произведением вещественных чисел? Как можно избежать накопление ошибки?

Nub
Сообщения: 35
Зарегистрирован: Пн май 06, 2013 11:46 am

Сообщение Nub » Ср окт 21, 2015 7:29 pm

у вас в дельфи была другая архитектура ЭВМ? :)
никак не избежать. говорили, что это одна из основных проблем программирования - учёт погрешностей при работе с вещественными числами. Мантисса и порядок оттаке :(

Chernykh_IL
Сообщения: 60
Зарегистрирован: Чт фев 02, 2006 11:55 am

Сообщение Chernykh_IL » Ср окт 21, 2015 7:58 pm

у вас в дельфи была другая архитектура ЭВМ?

В языках программирования (в делфи - точно) объявляется тип переменной. И, если, тип переменной "целый" , то сравнивать "=" корректно.
Это тоже на первом курсе объясняют.

КудяшоваГалина
Сообщения: 7
Зарегистрирован: Пн окт 19, 2015 7:11 pm

Сообщение КудяшоваГалина » Ср окт 21, 2015 8:05 pm

Я к сожалению на программиста не обучалась, но решала довольно много прикладных инженерных задач. И не разу не было такой проблемы, чтобы не получалось найти произведение вещественных чисел! Может можно как-то прописать точность? У вас нет предложений по решению этой задачи?

КудяшоваГалина
Сообщения: 7
Зарегистрирован: Пн окт 19, 2015 7:11 pm

Сообщение КудяшоваГалина » Ср окт 21, 2015 8:12 pm

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

Nub
Сообщения: 35
Зарегистрирован: Пн май 06, 2013 11:46 am

Сообщение Nub » Ср окт 21, 2015 9:04 pm

Chernykh_IL писал(а):если, тип переменной "целый" , то сравнивать "=" корректно.


кто-то утверждал противоположное?

Nub
Сообщения: 35
Зарегистрирован: Пн май 06, 2013 11:46 am

Сообщение Nub » Ср окт 21, 2015 9:12 pm

КудяшоваГалина писал(а):хотелось бы получить соответствующие статусу ответы.

наверное людям соответствующего статуса ваша проблема неинтересна :) да и мне, студенту, ясно, что вы делаете какую-то ерунду - умножаете на бесконечно малое и хотите, чтоб ответ был предсказуемым. Вот ваша прога на Си, выдаст ровно такую же ерунду, потому что машинная реализация вещественных чисел - та же, а чему равно f(-6) вообще удивитесь

Код: Выделить всё

#include <iostream>
using namespace std;

double f (int m) {
 double p=1.;
 double a=m;
 while (a<1) {
  a+=0.1;
  p*=a;
 }
 return p;
}
int main() {
 cout << f(-2) << " " << f(-3) << " " << f(-4) <<
  " " << f(-5) << " " << f(-6) << endl;
 cin.sync(); cin.get(); return 0;
}

КудяшоваГалина
Сообщения: 7
Зарегистрирован: Пн окт 19, 2015 7:11 pm

Сообщение КудяшоваГалина » Чт окт 22, 2015 1:54 am

Спасибо.

КудяшоваГалина
Сообщения: 7
Зарегистрирован: Пн окт 19, 2015 7:11 pm

Сообщение КудяшоваГалина » Чт окт 22, 2015 2:06 am

Бесконечно малого числа там не получается. Значит просто не доходит до 0. Ибо в маткаде при умножении на 0 всегда 0. Такого рода подзадачи часто встречаются при расчете траекторий,и шаг может быть еще меньше.

КудяшоваГалина
Сообщения: 7
Зарегистрирован: Пн окт 19, 2015 7:11 pm

Сообщение КудяшоваГалина » Чт окт 22, 2015 11:04 pm

Если посмотреть, какие получаются числа с шагом 0.1 например от -8 до 1 (result format - number of decimal places = 17), то увидим, что в результате стремительного нарастания ошибки в ноль мы не приходим, отсюда и неверные результаты. В таком случае целесообразно принять допустимую погрешность, то есть какие два числа мы считаем неразличимыми, вводим round.
p.s. более серьезные штуки обсуждались в свое время на Хабрахабре.
На заметку не сколько кодерам, сколько расчётчикам и инженерам, чтобы не получить в серьезных расчётах нелепые результаты.
Изображение

Nub
Сообщения: 35
Зарегистрирован: Пн май 06, 2013 11:46 am

Сообщение Nub » Пт окт 23, 2015 8:58 am

"бесконечно малое" я имел в виду то значение, которое получается вместо нуля. например,

Код: Выделить всё

double x1=0; //ноль
double x2=-0.1;
x2=x2*0.1+0.01; //уже не ноль

а вместо round нам говорили примерно так (тот же самый принцип)
К вещественным значениям в общем случае неприменима операция = ("сравнение") из-за неточного представления этих значений в памяти компьютера. Поэтому для вещественных переменных отношение вида a=b обычно заменяется на abs(a-b)<eps, где eps -- малая величина, определяющая допустимую погрешность.