LINUX.ORG.RU

Про округление...


0

0

Как-то написал я прогу на чистом хорошем ANSI C. Работала она себе спокойно под OS/2 и Win32. Решил недавно скомпилить ее под Linux и FreeBSD. Все нормально скомпилировалось, но с мат.операциями что-то плохо. Например, выражение ((31.6 - 8.2)/0.2) в проге, скомпилированной в OS/2 или винде, дает ровно 117.000000000000000 (переменные double), тоже самое в Linux и FreeBSD дает что-то вроде 116.999999999999986. Разница может и не большая, но имеет для меня принципиальное значение.

Я сделал тестовую прогу, что-то вроде

int main(void) { double tmp1, tmp2, tmp3;

tmp1 = 31.6; tmp2 = 8.2; tmp3 = 0.2;

printf("%3.15а \n", ((tmp1 - tmp2)/tmp3)); return 0; }

и она выдает в Linux и FreeBSD ровно 117.000000000000000! Т.е. если такой кусок кода выделить в чистом виде, то все работает нормально.

Вопрос: почему такое может быть? Почему в основной программе округляется плохо?

P.S. Пробовал ключи оптимизации - результаты те же. Использовался gcc 3.2.1

anonymous

Потому что это нормальное явление для вещественных чисел:
даже в одной и той же ОС на одной и той же машине любое вещественное число представимо в 3-х видах, например:

a - точное значение
x - приближенное

a=1.0

x = 1.0000000000000000 - первый вариант
x = 0.9999999999999999 - второй вариант
x = 1.0000000000000001 - третий вариант
ЭТО ОДНО И ТО ЖЕ ЧИСЛО, 
а называтся это накоплением погрешности. Оно есть всегда.
Не веришь мне, прикладному математику, обратись к спецлитературе:

Тихонов, Самарский "Численные методы"
Бахвалов, Жидков, Кабельков "Численные методы", например
Найти их в формате djvu можно на www.poiskknig.ru

popov_da
()
Ответ на: комментарий от popov_da

По стандарту (ANSI/ISO C) double это 10 значащих цифер...не забивайте голову ерундой. Был уже флейм тут на тему представимости десятичной дроби двоичной. Следуйте стандарту.

sS ★★★★★
()

Ох ты блин, ёлы-палы, ещё один из десятчной системы в двоичную и обратно плавучую арифметику переводить не умеет.

WidowMaker
()
Ответ на: комментарий от WidowMaker

Спасибо за обсуждение, не знал что по стандарту должно быть десять чисел. Но есть информация из компетентной книжки: http://www.library.cornell.edu/nr/bookcpdf/c20-1.pdf

Так вот там написано что если использовать double, то точность достигается порядка 2*10(-16). Или как тогда перевести выражение "floating-point precision" ???

anonymous
()
Ответ на: комментарий от anonymous

Так. Бегом курить авторитетные школьные книги по арифметике. Дабы понять, что точность - это разрядность мантиссы (двоичная разрядность, забудь про десятичную навсегда), а ты тут - округлённый десятичный порядок показываешь.

WidowMaker
()
Ответ на: комментарий от anonymous

А в чем проблема? Допустим, что достигается указанная Вами точность (она ограничена разрядностью мантиссы), это никак не вляет на принципиальную невозможность точно представить какое-нть число в данном формате - в итоге получаете вместо 0.1 - 0.10000000000000001.

phoenix ★★★★
()
Ответ на: комментарий от anonymous

> Так вот там написано что если использовать double, то точность достигается порядка 2*10(-16).

ну так между 0.116999999999999986e3 и 0.117e3 отличие как раз в 17-ом десятичном знаке.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

Все понял. Каюсь. :) Всем спасибо.

anonymous
()
Ответ на: комментарий от dilmah

Совершенно согласен со всем вышесказанным. Просто господин anonymous первый раз столкнулся с вычислительными задачами. Со своей стороны хочу заметить, что достижения точности 0.5*10^-5 - 0.5*10^-7 более чем достаточно для практически всех расчетных задач науки и техники.

popov_da
()
Ответ на: комментарий от popov_da

> Со своей стороны хочу заметить, что достижения точности 0.5*10^-5 - 0.5*10^-7 более чем достаточно для практически всех расчетных задач науки и техники

не, я как то для вычислительной геометрии писал код. Там действительно качественный код должен использовать что-то типа адаптивной арифметики. Мистер Джонатан Шевчук спец по этому вопросу.

dilmah ★★★★★
()
Ответ на: комментарий от cpu

>А также никогда не храните бабло в float, double и long double. Используйте только целые типы.

Писали "чёрную бухгалтерию" ? ;)

У меня коллега этот этап проходил в начале 90-х в период расцвета кооперативного движения ;) Как CFD-шник, он научил своё поделие работать с жуткой скоростью с огромными базами данных. Только формат данных был нестандарный ;) В одной конторке (для которой и была писана сия система) она долгие годы стояла на чёрной практически без глюков (на белой уже тогда стояла 1C) На аналогичном железе рвала последнюю по скорости как бобик грелку. Скорость проводки различалась раз в 100 наверное. Правда не имела поддержки сети. Если бы успел подсуетиться - бегала бы сейчас это чудо бухгалтерское по сетке на PVM или MPI, вот бы смеху то было бы ;)

Эх. Чем только люди не занимались в те весёлые времена ;)

sS ★★★★★
()
Ответ на: комментарий от anonymous

>CFD это вычислительная гидродинамика?

Да.

sS ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.