Почему 0.05 * 0.006 = 0.00030000000000000003?
От: Аноним  
Дата: 22.07.08 14:14
Оценка:
Visual Studio 2005 & C#

Вот простенький пример кода:

double a = 0.05;
double b = 0.006;
double c = a * b;


Останавливаю в режиме отладки и вижу, что c = 0.00030000000000000003. 20 знаков после запятой!!! Почему??? Ведь должно получиться 0.0003.... В чем дело, кто-нибудь может объяснить? Хотя для типа double в msdne четко сказано, 15 значащих цифр...

Это не благой интерес. Очень нужно, чтобы все было по нормальному...

Есть расчет очень сложного, циклического алгоритма. После каждой итерации данные (типа double) записываю в БД Access. При отладке по шагам в Visual Studio числа имеют длину 20 знаков после запятой, а при записи в Access они укорачиваются до 18 знаков... В принципе такая точность мне и не нужна, я бы ограничился 15 знаками. Но нужно делать "расчет с продолжением", т.е. нужно открывать файл БД, ранее расчитанный, из него считываю 2 последние строчки и продолжаю вычисления, основываясь на этих данных... Так вот эти считанные данные (ранее сохраненные) отличаются на 2 последних знака после запятой, поэтому расчет например 100.000 без продолжения (за раз) отличается от расчета например сначала 50.000, потом еще 50.000. Сначала разница ничтожна, но потом сказывается "лавинный эффект" и при большом количестве итераций разница уже существенна...

И это всё из-за того, что получается в примере выше такая фигня.

Из-за того, что в памяти хранится не 0.0003 а 0.00030000000000000003 постепенно накапливается ошибка...

Кто виноват и что делать?
double типы данных
Re: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: Lloyd Россия  
Дата: 22.07.08 14:21
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>и что делать?


Использовать decimal
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: GarryIV  
Дата: 22.07.08 14:24
Оценка: 35 (1) +2 :)))
Здравствуйте, Аноним, Вы писали:

А>Кто виноват и что делать?


Кто виноват: Ты прогулял лекцию на которой читали о числах с плавающей запятой...
Что делать: Прочитай отсюда http://www.rsdn.ru/article/alg/float.xml
Автор(ы): Сергей Холодилов
Дата: 15.03.2008
Если яблоко поровну разделить на троих, каждому достанется треть. Так в нашу жизнь входят дроби, примерно с теми же целями входят они и в программирование.. Но реализация дробей в виде типов данных float/double ведёт себя не совсем "математично". В чём причина отличий, как минимизировать их влияние на результат вычислений, как же всё это всё-таки реализовано и почему запятая плавает — читайте в статье.
и до просветления
WBR, Igor Evgrafov
Re[2]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: TK Лес кывт.рф
Дата: 22.07.08 14:26
Оценка:
Здравствуйте, GarryIV, Вы писали:

А>>Кто виноват и что делать?

GIV>Кто виноват: Ты прогулял лекцию на которой читали о числах с плавающей запятой...

ИХМО, про это даже в школе рассказывают
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 22.07.08 14:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Кто виноват и что делать?


Используйте decimal и посмотрите эти ссылки:
Числа с плавающей запятой и их особенности
Округление? Почему так?
Автор: zbanned
Дата: 03.07.08

double (неправльно щитает)
Автор: ywlepak
Дата: 05.02.07

Проблема преобразования типов
Автор: Tezcatlipoca
Дата: 23.09.04


Поиском можно еще много по этой теме найти.
Re[2]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: Аноним  
Дата: 22.07.08 14:40
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, Аноним, Вы писали:


А>>Кто виноват и что делать?


N>Используйте decimal и посмотрите эти ссылки:

N>Числа с плавающей запятой и их особенности
N>Округление? Почему так?
Автор: zbanned
Дата: 03.07.08

N>double (неправльно щитает)
Автор: ywlepak
Дата: 05.02.07

N>Проблема преобразования типов
Автор: Tezcatlipoca
Дата: 23.09.04


N>Поиском можно еще много по этой теме найти.


Спасибо за ссылки. Тип decimal удвоит объем данных... А при хранении 100.000 строк в БД это ой как существенно... Компилятор Borland Builder кстати этот пример посчитал абсолютно правильно...
Re[2]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: Idsa Россия  
Дата: 22.07.08 16:43
Оценка:
Здравствуйте, GarryIV, Вы писали:

GIV>Кто виноват: Ты прогулял лекцию на которой читали о числах с плавающей запятой...

GIV>Что делать: Прочитай отсюда http://www.rsdn.ru/article/alg/float.xml
Автор(ы): Сергей Холодилов
Дата: 15.03.2008
Если яблоко поровну разделить на троих, каждому достанется треть. Так в нашу жизнь входят дроби, примерно с теми же целями входят они и в программирование.. Но реализация дробей в виде типов данных float/double ведёт себя не совсем "математично". В чём причина отличий, как минимизировать их влияние на результат вычислений, как же всё это всё-таки реализовано и почему запятая плавает — читайте в статье.
и до просветления

Что Вы на человека набросились?!
Вопрос в том, почему в MSDN говорится, что у double 15 знаков после запятой, а дебаггер показывает 20. Мне тоже непонятно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1096>>
Re[3]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: madbinom  
Дата: 22.07.08 16:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, nikov, Вы писали:


N>>Здравствуйте, Аноним, Вы писали:


А>>>Кто виноват и что делать?


N>>Используйте decimal и посмотрите эти ссылки:

N>>Числа с плавающей запятой и их особенности
N>>Округление? Почему так?
Автор: zbanned
Дата: 03.07.08

N>>double (неправльно щитает)
Автор: ywlepak
Дата: 05.02.07

N>>Проблема преобразования типов
Автор: Tezcatlipoca
Дата: 23.09.04


N>>Поиском можно еще много по этой теме найти.


А>Спасибо за ссылки. Тип decimal удвоит объем данных... А при хранении 100.000 строк в БД это ой как существенно... Компилятор Borland Builder кстати этот пример посчитал абсолютно правильно...


Компилятор чего? СиППбилдеровский раньше проверял (в исполняемом коде) на отличие от нуля значения 1 в вечном цикле.
Re[3]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: vmpire Россия  
Дата: 22.07.08 17:01
Оценка: +1
Здравствуйте, Idsa, Вы писали:

I>Вопрос в том, почему в MSDN говорится, что у double 15 знаков после запятой, а дебаггер показывает 20. Мне тоже непонятно.

Где Вы нашли "15 знаков после запятой"? Можно ссылку?
Не "15 знаков после запятой", а "15 значащих цифр". Значащих десятичных цифр
Двоичных цифр в мантиссе 53, следовательно, десятичных log10(2^53) = 15.9546, то есть 15 — точно, а 16 — как повезёт.
Но незначащих цифр может быть хоть сто, так как двоичные дроби не всегда точно представимы в десятичном виде.
Поэтому, в Debug показывают с запасом.
Re[2]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: PaulMinelly  
Дата: 23.07.08 04:26
Оценка:
А>>и что делать?
L>Использовать decimal

Каким стандартом IEEE регулируется decimal?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: Lloyd Россия  
Дата: 23.07.08 07:54
Оценка:
Здравствуйте, PaulMinelly, Вы писали:

L>>Использовать decimal


PM>Каким стандартом IEEE регулируется decimal?


Представления не имею.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[3]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: yoriсk.kiev.ua  
Дата: 23.07.08 08:36
Оценка:
Здравствуйте, PaulMinelly, Вы писали:

А>>>и что делать?

L>>Использовать decimal

PM>Каким стандартом IEEE регулируется decimal?


Что такое IEEE и как он влияет на реальную жизнь?

P.S. Кстати, каким-то регулируется.
Re: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: Nuseraro Россия  
Дата: 23.07.08 12:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>double a = 0.05;
А>double b = 0.006;
А>double c = a * b;
А>


А>Останавливаю в режиме отладки и вижу, что c = 0.00030000000000000003.


A> Хотя для типа double в msdne четко сказано, 15 значащих цифр...


А>Что делать?


Ну если чётко сказано, что 15, то отбрасывай после 15 цифр всё. Ну или мб нужно 16ую учесть.
Homo Guglens
Re[3]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: _d_m_  
Дата: 24.07.08 03:04
Оценка:
Здравствуйте, PaulMinelly, Вы писали:

А>>>и что делать?

L>>Использовать decimal

PM>Каким стандартом IEEE регулируется decimal?


Тем же, что и int. Децимал тривиален — что там регулировать?
Re[4]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 24.07.08 05:54
Оценка:
Здравствуйте, _d_m_, Вы писали:

___>Тем же, что и int. Децимал тривиален — что там регулировать?


Я бы не сказал
Автор: nikov
Дата: 29.03.07
, что тривиален.
Re[5]: Почему 0.05 * 0.006 = 0.00030000000000000003?
От: _d_m_  
Дата: 24.07.08 21:08
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, _d_m_, Вы писали:


___>>Тем же, что и int. Децимал тривиален — что там регулировать?


N>Я бы не сказал
Автор: nikov
Дата: 29.03.07
, что тривиален.


Ну есть свои особености реализации. Скажем по другому: он не настолько сложен, чтобы регулировать его специальными стандартами.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.