RE: double ошибки представления как победить?
От: Аноним  
Дата: 16.07.14 10:23
Оценка: -2
Последнее сообщение ибо я не понимаю что мне тут могут помочь, если уровень низкий.

N>И что видим на выходе:


N>
N>0.059999999999999997779553950749686919152736663818359375
N>


Да как же вы не поймете(!!!!) — это функция ВЫВОДА, она выводит.

Если в 64 бита я могу запихать:

"3ff0000000000000" это 1
"3ff0000000000001" это 1.0000000000000002

N>Для Вас новость, что вычисления с плавающей точкой в принципе неточные? И что ни одно число, если оно не кратно степени двойки, не может быть представлено точно в каком-то из стандартных IEEE binary форматах? Тогда у Вас ещё очень много открытий. Вот, например, второй пример, которому учат в вузе на соответствующем курсе:



Блин —

Еще раз и последний
1) При делении, умножении и в "константе в ТЕКСТЕ программы" значенние ( пример ) 0.06 равно = 0.059999999999999998

Ощибка от 0.06 равна — 0.00000000000002

В формате это значение равно 0.06 = "3faeb851eb851eb8"
Если мы прибавим к нему минимально возможное тут значение — в последний разряд... там где eb8 будет не 8 (1000) а 9 ( 1001). То значение будет уже
"0.060000000000000005" или в формате = "3faeb851eb851eb9"

Разница от 0.06 больше и равна = 0.0000000000005

Следующее минимальное изменение дает уже 0.060000000000000012 это "3faeb851eb851eba"

Вот мы имеем проблему


2) Если мы НАПРИМЕР прибавим к 0.05 + 0.01 то мы НЕ получим ТО ЖЕ что и в варианте с умножением, делением и в константе в тексте(!!!). То есть мы получим "0.060000000000000005" или в формате = "3faeb851eb851eb9"


И в итоге мы имеем "проблему" — что в результате умножения мы получаем форму такуюже как в константе а в результате сложения мы получаем следуюющее значение.

Надо найти алгоритм ПРИВЕДЕНИЯ из результата сложения всегда к форме представления или к тому же результату что и в результате умножения.

3f847ae147ae147a — это 0.0099999999999999985
3f847ae147ae147b — это 0.01 (форма представления в языке )
3f847ae147ae147с — это 0.010000000000000002

сложим — 0.050000000000000003 + 0.01 =

3fa999999999999a + 3f847ae147ae147b = 3faeb851eb851eb9 = 0.060000000000000005

сложим — 0.050000000000000003 + 0.0099999999999999985 = 0.059999999999999998

3fa999999999999a + 3f847ae147ae147a = 3faeb851eb851eb8 = 0.059999999999999998


N>Как вы думаете, какой ответ она напишет? 9.9? Нет, она напишет 10. Потому что внутри этот 10 является 9.9999999999999804600747665972448885440826416015625.


N>И вот там же на лекциях чётко говорят: хотите сравнивать числа на равенство, полученные из разных даже очень простых вычислений? Нет проблем, определите так называемый эпсилон для такого сравнения и проверяйте abs(_d3 — _d4) < epsilon.

N>Чему этот epsilon будет равен в Вашем случае — не знаю. Но если Вы хотите двух цифр после запятой, он равен 0.005.

Уважаемый — вы гоните БАНАЛЬНОСТИ!! Да и к тому же ощибочные = эпсилон для дабла это

#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */

И означает оно то минмальное значение которое позволяет различить два числа равные ( почти ) единице.

Но не суть — проблема не в этом.

А>>Достал квт совсем.


N>Конечно, он "достанет", если, нифига в теме не зная и не представляя особенности, сунуться с заявлением "почините-ка это мне", считая, что это какие-то "ошибки представления". Нету тут ошибок представления, не надейтесь. Есть законно сделанные по всем правилам вычисления и есть естественные проблемы округлений при таких вычислениях. Не нравится — у Вас есть масса вариантов:


N>1. Применить вместо этого библиотеку работы с плавающей точкой с десятичными порядком и мантиссой. Это очень правильный метод, если задача — не из матфизики, а из финансов, бухгалтерии и т.д.


Мне на надо с целыми мне надо с даблами.

N>2. Применять округление вручную, как в прошлом моём ответе.


Какое округление еще.

N>3. Сравнивать через epsilon, как в этом сообщении.

N>4. Уйти вообще от проблемы сравнения через замену алгоритма.
N>5. Бросить всё и заплакать.

N>Выбирайте.


Вообщем, попробуйте представить, что вы сейчас говорите с человеком гораздо лучше вас разбирающемся в "проблеме", и исходя из этого понять что готовых ответов в области банальностей тут нет.

Это я говорю вам, чтобы вы вообще в принципе поменяли подход — вас спрашивают не школькники и студенты, а люди разбирающиеся лучше вас, и следовательно есть два варианта :

1)Думать, вместе, советоваться уточнять и прочее
2)Просто молчать. Если вас это не интересует.
))

Все — пока. В смысле доствидания.
Re[2]: You must be new here
От: Qbit86 Кипр
Дата: 16.07.14 10:49
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Последнее сообщение ибо я не понимаю что мне тут могут помочь, если уровень низкий.

А>Это я говорю вам, чтобы вы вообще в принципе поменяли подход — вас спрашивают не школькники и студенты, а люди разбирающиеся лучше вас, и следовательно есть два варианта :

Аноним, ты какой-то агрессивный. К тому же не попадаешь в ветку комментариев, порождая каждый раз новый топик.
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: double ошибки представления как победить?
От: K13 http://akvis.com
Дата: 16.07.14 10:57
Оценка:
А>Это я говорю вам, чтобы вы вообще в принципе поменяли подход — вас спрашивают не школькники и студенты, а люди разбирающиеся лучше вас

С чего вдруг? иногда тупят не только школьники. Непонимание матчасти именно у топикстартера.
еще раз: 0.1 + 0.1 не обязана равняться 0.2. от слова "вообще".
бывает хлеще. когда 0.1 + 0.1 не равна 0.1 + 0.1 :
double foo()
{
  return 1.0 / 7;
}

assert( foo() == 1.0 / 7 );


и вдруг срабатывает ассерт. а может и не сработать (зависит от компилятора и его опций).
и ничего удивительного в этом нет.

никто никогда не обещал, что результаты вычислений будут совпадать. ВСЕ вычисления с плавучкой -- приближенные.
даже константное выражение в коде программы.
Re[2]: double ошибки представления как победить?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 16.07.14 11:48
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Последнее сообщение ибо я не понимаю что мне тут могут помочь, если уровень низкий.


Верно, Вам надо ещё многому учиться, прежде чем понять, что тут говорят.

N>>И что видим на выходе:

N>>
N>>0.059999999999999997779553950749686919152736663818359375
N>>

А>Да как же вы не поймете(!!!!) — это функция ВЫВОДА, она выводит.

Кто бы спорил

А>Если в 64 бита я могу запихать:


А>"3ff0000000000000" это 1

А>"3ff0000000000001" это 1.0000000000000002

Нет, в последнем случае это 1.0000000000000002220446049250313080847263336181640625. А 1.0000000000000002 это приближённое представление по принципу "ограничим самой старшей из цифр, которая меньше дискрета представления".

А>Блин —

А>Еще раз и последний
А>1) При делении, умножении и в "константе в ТЕКСТЕ программы" значенние ( пример ) 0.06 равно = 0.059999999999999998
А>Ощибка от 0.06 равна — 0.00000000000002

Да, именно так. И почему Вас это удивляет?

А>В формате это значение равно 0.06 = "3faeb851eb851eb8"


Да, оно "равно" 0.06, ибо, согласно C99 (пункт 7.19.6.1, параграф 8), '%g' выбирает формат или по %e (с явной печатью степени), или по %f (с фиксированной точкой), а, для %f, цитирую,

If the precision is missing, it is taken as 6

.
То есть если Вы выводили по умолчанию, оно использовалось как "%.6f". И далее общее правило для всех режимов (%f, %e, %g):

The value is rounded to the appropriate number of digits.

Ключевое слово — "rounded".

Или Вы опять будете настаивать на C++? Тогда, например, в C++11 final draft таблица в пункте 27.5.5.2 говорит про те же самые 6 цифр по умолчанию. Цитировать тут таблицу не буду, уж извините.

Почему я Вам и говорил: выберите, как именно Вы будете печатать его, потому что режим по умолчанию скрывает эти подробности, и различия в double в минимальном бите в нём не печатаются.

А>И в итоге мы имеем "проблему" — что в результате умножения мы получаем форму такуюже как в константе а в результате сложения мы получаем следуюющее значение.


Нет. Вы НЕ получаете "форму такую же как в константе". Вы получаете другую форму, которую не можете отличить из-за своего неумения или нежелания прочитать и осознать, что и как делает то средство, которое Вы применяете для получения десятичного представления.

А>Надо найти алгоритм ПРИВЕДЕНИЯ из результата сложения всегда к форме представления или к тому же результату что и в результате умножения.


То есть Вам нужно было округлить до сотых? Или до миллионных, чтобы представляющиеся одинаково значения и были равны между собой, даже если это представление теряет точность?

Ну тогда Вам флаг в руки и комбинация из frexp(), round() и ldexp() из <math.h> навстречу.

А>Уважаемый — вы гоните БАНАЛЬНОСТИ!! Да и к тому же ощибочные = эпсилон для дабла это

А>#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
А>И означает оно то минмальное значение которое позволяет различить два числа равные ( почти ) единице.

Это другой эпсилон. К сожалению, тут некоторое смешение терминов. Но тот, кто в теме, различает их с ходу. Увы, к Вам это сегодня неприменимо.

N>>1. Применить вместо этого библиотеку работы с плавающей точкой с десятичными порядком и мантиссой. Это очень правильный метод, если задача — не из матфизики, а из финансов, бухгалтерии и т.д.

А>Мне на надо с целыми мне надо с даблами.

А это будет с плавающей точкой, а не с целыми. Ссылки Вам дали.

N>>2. Применять округление вручную, как в прошлом моём ответе.

А>Какое округление еще.

Самое простое. Например, round(x*100)/100 округляет до 1/100. Вы знаете, до какого значения Вы можете округлить без потери существенной части значения?

А>Это я говорю вам, чтобы вы вообще в принципе поменяли подход — вас спрашивают не школькники и студенты, а люди разбирающиеся лучше вас,


"Люди, разбирающиеся лучше нас" не делают таких нелепейших ошибок и умеют внятно описывать проблему. Так что — урежьте осетра.

А>1)Думать, вместе, советоваться уточнять и прочее

А>2)Просто молчать. Если вас это не интересует.
А>))

А>Все — пока. В смысле доствидания.


Да мне-то что. Это у Вас была проблема.
The God is real, unless declared integer.
Re[2]: double ошибки представления как победить?
От: lxa http://aliakseis.livejournal.com
Дата: 02.08.14 10:36
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Последнее сообщение ибо я не понимаю что мне тут могут помочь


Дайте половину!
Re[2]: double ошибки представления как победить?
От: Erop Россия  
Дата: 02.08.14 19:45
Оценка:
Здравствуйте, Аноним, Вы писали:

N>>Чему этот epsilon будет равен в Вашем случае — не знаю. Но если Вы хотите двух цифр после запятой, он равен 0.005.


А>Уважаемый — вы гоните БАНАЛЬНОСТИ!! Да и к тому же ощибочные = эпсилон для дабла это


А>#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */


Он не "банальности гонит", а неточно излагает.
На всякий случай, что бы не было недопонимания, ОБЫЧНО, при работе с даблами, оценивают не только сам результат,
но и его точность. То есть про два значения обычно известно, с какой точностью они получены, и, соответственно, могут ли быть одним и тем же значением, просто по разному вычисленным, или нет.
Если оценка даёт априорную абсолютную погрешность. то её можно задать просто числом, которое задаст полуширину диапазона, и обычно его обозначают как эпсилон.
Если есть априорная оценка относительной погрешности, то задавать диапазон надо чуть хитрее.
Но, в любом случае, при нормальных вычислениях стараются делать так, что бы до DBL_EPSILON дело не доходило...

А>Но не суть — проблема не в этом.


Я не читал основную ветку внимательно, но так и не понял, что конкретно тебе надо. Суть проблемы ускользнула от меня...

Если таки хочешь помощи -- поясни конкретно что тебе надо.
И да, выражение (0.05 + 0.01)-(0.6 / 10.) нулю равно быть не обязано...
Дабловые нули они такие
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.