LINUX.ORG.RU

[C++] реализация чисел с плавающей точкой на int'ах

 


0

2

Столкнулся с ограничениями на тип double. По ряду причин усложнение алгоритма менее желательно чем потеря части производительности. Первое что пришло в голову это написать свой класс в котором реализовать число с плавающей точкой через int'ы. Второе что мне пришло в голову это то что таких реализаций должен быть вагон. Где мне посмотреть что-то подобное? Требования в порядке убывания: кроссплатформенность, lgpl/bsd, голый стандартный C++, не gnu code style.

★★★★★
Ответ на: комментарий от KblCb

Это все хорошо, конечно. Но давайте я два примера приведу.

  • Надо два double на равенство сравнить, оба получены в результате каких-то вычислений. Способ a == b конечно хорош, и отлично читаем человеком, далеким от этих сложных вычислений. Только не работает. Недавно тут один товарищ на эту тему жаловался.
  • Надо было как-то раз получить номер ячейки (все одинакового размера и начинаются с 0), в которой лежит заданная точка. Метод
    int num = (int)floor(x / size_x);
    

    или даже

    int num = (int)(floor(x / size_x) + 0.5);
    

    очень прост для восприятия и понимания. Только вот не работает, из-за чего возникают странные баги. К примеру, число x=3 в памяти в результате вычислений представлялось как 2,99...94, и при вычислении (размер ячейки - единица) радостно превращалось в 2, что слегка ожиданиям не соответствует.

Поэтому собственно вариантов несколько: либо можно обратиться к умным математикам, которые придумывают специальные алгоритмы, уменьшающие ошибку (и делают соответствующие доказательства! Алгоритмы сложнее, но зато работают), либо можно всегда держать накапливающуюся ошибку в уме (чтобы не огрести неожиданно), реализуя обычный алгоритм, либо реализовать все просто и human readable, а потом бегать с бубном и удивляться, чего же оно не работает.

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

>Поэтому собственно вариантов несколько: либо можно обратиться к умным математикам...

Лучше не обращаться. Будет только хуже. Умные математики далеки от земных проблем.

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

> К примеру, число x=3 в памяти в результате вычислений представлялось как 2,99...94, и при вычислении (размер ячейки - единица) радостно превращалось в 2, что слегка ожиданиям не соответствует. floor - отбрасывает целую часть, т.е. floor(2,999) = 2, Скобку в другое место ставь: int num = (int)(floor(x / size_x + 0.5); - получишь floor(2,999 + 0,5) = 3, т.е. то что ты ожидал

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

Скобку в другое место ставь: int num = (int)(floor(x / size_x + 0.5); - получишь floor(2,999 + 0,5) = 3, т.е. то что ты ожидал

Ну и сразу вылезет floor(2,6 + 0,5) = 3, т.е. 2,6 вместо двух превратится в 3, что тоже довольно странно.

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

Помню одну книгу по выпуклому анализу, так там эпсилон-окрестности чуть ли не на каждой странице... В одном графическом редакторе я использую floor для определения участка перерисовки, и ничего, работает :)

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

что странного? математическое округление же. 2,6 округляется до 3.

p.s. особых проблем с double не имел, если четко сформулирована задача.

dpt-ru
()
Ответ на: комментарий от dave

Ну в графическом редакторе все и должно работать. :)

А у был очень баг из-за этого флоата: при создании больших графов (~10^7 ребер) в некоторых случаях возникала описанная ошибка, что приводило к тому, что группа ребер из графа ошибочно выбрасывалась, после чего на этом графе вычисления были неправильными. А на маленьких графах ничего не возникало. Был в восторге от процесса отладки.

Кстати, по поводу сравнения double'ов - вполне устроил вот этот пост, может кому пригодится.

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

Когда-то давно держал в руках учебник по интервальной математике, так там утверждалось, что довольно приличное количество численных методов при доказанной сходимости в реальности могут даже не сходится из-за неточных вычислений, т.е. погрешности! Другими словами, теоретическая сходимость без учета интервалов не дает еще гарантии. Некорректные методы получаются. Вот такие дела. Вообще, сложная тема. Очень матанная.

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

ок, просто надо понимать что пишете, пост читал бегло, floor(x + .5) - это стандартное математическое округление, оно вам не к чему. в вашем случае нужно добавлять небольшое число, к примеру floor(x + .00001)

p.s. пишу опять же бегло, но смысл я думаю ясен - добавляем небольшое значение, которое подходит под условия задачи

dpt-ru
()
Ответ на: комментарий от gizzka

Прошло уже одинадцать лет. Но название примерно такое: «Интервальная математика» или «Интервальные вычисления». Переплет твердый, хороший. Коричневого цвета. Кажется, авторы иностранные. Уже не помню.

А так, во многих случаях спасает регуляризация или прочие хитрые методы. И как говорил один мой приятель, который занимался краевыми задачами в аспирантуре: «ни за что не сяду в тот самолет, который будет спроектирован с учетом моих результатов!» ;)

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

хотел ведь написать «одиннадцать» :)

dave ★★★★★
()
Ответ на: комментарий от dpt-ru

ок, просто надо понимать что пишете, пост читал бегло, floor(x + .5) - это стандартное математическое округление

Вы, пожалуйста, определитесь, с кем хотите спорить: со мной или с анонимусом (который тоже бегло прочитал, не разобрался и что-то не то сказал). И заодно определитесь, что именно Вы хотите оспорить.

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

нужно добавлять небольшое число, к примеру floor(x + .00001)

За это решение надо отрывать руки. Я уже давал ссылку на объяснение, почему. Почитайте.

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

За это решение надо отрывать руки. Я уже давал ссылку на объяснение, почему. Почитайте.

lol. мсье теоретик? себе руки отрывайте, когда свои задачи решить не можете.

во-первых - я вам предложил не DBL_EPSILON а конкретную величину, во-вторых я указал

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

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

как правило точности хватает. программы как-то пишутся, задачи как-то решаются... мистика...

если нужна сверх-точность - то встают вопросы как автора темы.

dpt-ru
()
Ответ на: комментарий от dpt-ru

во-первых - я вам предложил не DBL_EPSILON а конкретную величину

Вы в курсе, чем отличается «относительный» от «абсолютный»?

Прочитайте ещё раз про слона в посудной лавке. Ваша 0.0001 мало чем от DBL_EPSILON в этом случае не отличается.

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

спорьте сами с собой дальше.

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

как правило точности хватает. программы как-то пишутся, задачи как-то решаются... мистика...

dpt-ru
()
Ответ на: комментарий от gizzka

> Ага, а самолет вот назло возьмет и взлетит. :)

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

А у меня все проще. Упала или подвисла программа - клиент ее просто перезапустил :)

dave ★★★★★
()
Ответ на: комментарий от dpt-ru

> если нужна сверх-точность - то встают вопросы как автора темы.

Это еще надо смотреть, что за задача. А вдруг она некорректная?

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