LINUX.ORG.RU

Необходимость Boost.Multiprecision

 , , , точность,


1

1

Добрый день.
Есть необходимость производить некоторое количество геометрических расчетов. Поиск точек пересечения, некоторые операции с векторами на плоскости и т.п. Так вот столкнулся с известными проблемами double (потеря точности). Как бы вы сделали, заморачивались бы с double самостоятельно или просто взяли бы готовую библиотеку, которая позволяет представлять числа с фиксированной точностью (Boost.Multiprecision)?

★★★★★

Последнее исправление: rumgot (всего исправлений: 1)

Сначала взял бы готовую, а если производительность конечного продукта недостаточна и упирается в эту бибилотеку, тогда уже пытался перебирать альтернативы и, на худой конец, велосипедить

annulen ★★★★★
()
Ответ на: комментарий от i-rinat

Может и хватит. В бусте подкупает возможность использовать некоторые типы, которые header-only.

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

В boost.multiprecision есть и поддержка libquadmath. Просто если в проекте не было буста, часто по религиозным причинам его не хотят тянуть в зависимости.

i-rinat ★★★★★
()
Ответ на: комментарий от rumgot

Я такие библиотеки пару раз только пробовал. Сейчас глянул примеры у mpreal и они как-то чище выглядят чем у boost, в котором может быть больше функциональности. Но вообще заменить одну библиотеку другой при использовании перегруженных операторов не сильно сложно.

xaizek ★★★★★
()

Ради интереса, что за задача для которой не хватает double?

С float понятно - в масштабе планеты, например, оно даёт погрешность в метры, что не подходит, например, для интерактивных карт. Но запросто решается переходом в локальную систему отсчёта (проще говоря, когда начало координат под боком), ибо в GPU double пихать всё равно особо не попихаешь. А вот что за задача такая где не хватает double?

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

Получается два радиус-вектора, которые коллинеарны ( по косвенному условию), но их координаты рассчитываются независимо. И при проверке их коллинеарности (проверка на равенство частных от деления составляющих координат векторов друг на друга (x1/x2==y1/y2 ?)) получается, что у этих частных различаются 10 знаки после запятой и соответственно они получаются не коллинеарными (сравнивается модуль разницы чисел с epsilion). И тут я вижу два пути: любо делать функцию сравнения менее точной, т.е. сравнивать не с epsilion, а скажем с 0.000001 (этой точности достаточно) или (что мне больше нравится) использовать библиотеку, которая позволяет использовать типы с фиксированной точностью.

rumgot ★★★★★
() автор топика
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от slovazap

Еще прочитал, что double можно округлить до требуемого количества знаков после запятой так:

std::round(x * 1000) / 1000;
Но после деления на 1000 после запятой в позициях после третьей получаются не нули.

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

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

rumgot ★★★★★
() автор топика

Если речь идёт про расчёты - ты на этот вопрос хорошо ответит только составлявший формулы или разобравшийся в них.

Например - double можно просто округлять до нужной точности на каждом шаге вычислений.

Тащить на любой чих в зависимости новую либу нужно только если велосипед ощутимо дороже. Да и то не всегда.

Но есть варианты. Например, если это poc точно на выброс, то можно брать любой мусор. Или если продавать это никому не собираешься. В общем, если это проект с заведомо коротким циклом жизни или на выброс, а так же если велосипед соизмерим по затратам с 1/20 стоимости проекта(но тут тоже можно думать).

Nmp практика конечно же показывает, что я не прав.

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

Ну точного значения повышенная точность и фиксированная точка всё равно не дадут, это может только рациональная длинная арифметика, и то только если в формуле ничего кроме +-*/ нет. Поэтому в любом случае придётся сравнивать с какой-то погрешностью, значит в доп. библиотеках смысла нет, к тому же они медленнее в разы.

Алсо, есть мнение что если в каких-то геометрических расчётах что-то проверяется на равенство (хоть напрямую, хоть с epsilon, хоть с 0.00001), то это абсолютно точно ошибка. За этой коллинеарностью наверняка стоит реальная физическая величина у которой есть реальный допустимый диапазон, вот на попадание в него и нужно сравнивать.

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

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 3)
Ответ на: комментарий от slovazap

Ну точного значения повышенная точность и фиксированная точка всё равно не дадут

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

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

я бы считал не коллинеарность векторов

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

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

И тут я вижу два пути: любо делать функцию сравнения менее точной, т.е. сравнивать не с epsilion, а скажем с 0.000001 (этой точности достаточно) или (что мне больше нравится) использовать библиотеку, которая позволяет использовать типы с фиксированной точностью.

Вот нихера не понимаю, если вот это верно на 100%: «сравнивать ... с 0.000001 (этой точности достаточно)», то на кой ляд тащить другие либы? Это такая разновидность мазохизма, перфекционизма, или какого-то другого онанизма?

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

Потому что «пока достаточно». А через некоторое время может быть и недостаточно. К тому же это сравнение выглядит костыльно. А если будут числа с фиксированным количеством знаков после запятой, то их можно будет сравнивать обычным == (вот тут кстати не уверен, напишите, если ошибаюсь).

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

Потому что «пока достаточно».

Выше об этом не было ни слова ))

А через некоторое время может быть и недостаточно.

От чего это зависит? От фазы Луны? Это можно как-то определить/рассчитать заранее?

К тому же это сравнение выглядит костыльно.

Ни разу. Вот сравнение плавающих «в лоб» выглядит идиотией.

А если будут числа с фиксированным количеством знаков после запятой, то их можно будет сравнивать обычным ==

С потерей скорости. И с потерей точности на каждой операции, что очень быстро может привести к ошибке. В пределе: пусть нам достаточно целых чисел, разделив 10 на 3 и опять умножив на 3 мы не получим 10. Так и вы со своей фиксированной запятой.

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

Выше об этом не было ни слова ))

Так и вопрос не в этом был.

От чего это зависит? От фазы Луны? Это можно как-то определить/рассчитать заранее?

Можно наверное. Но пока не уверен.

Ни разу. Вот сравнение плавающих «в лоб» выглядит идиотией.

Так и не спорю.

разделив 10 на 3 и опять умножив на 3 мы не получим 10

Смотря сколько знаков после запятой у результата.

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

Смотря сколько знаков после запятой у результата.

С каким количеством знаков после запятой ты получишь 10/3*3 == 10?????

Ай ну, пиши как хочешь...

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

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

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

Так ведь мне не нужна повышенная точность, мне нужна ограниченная

Да, поэтому ничего сверх double тебе и не нужно, и, более того, ничего не даст. Кроме тормозов и неудобства.

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

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

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

Это округление только при выводе через поток.

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

Округлять переменную — бессмысленное занятие. Сам подумай — ты пытаешься обрезать цифры в десятичном представлении числа, но процессор оперирует с двоичным представлением. Некоторые числа, представление которых в десятичной системе конечно, в двоичной системе будут иметь бесконечное число цифр. Например, 0,1₁₀.

Если нужно отбрасывать цифры во время расчётов, считай сразу в десятичной системе счисления.

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

считай сразу в десятичной системе счисления

Но поскольку встроенные типы с плавающей точкой имеют двоичное представление, нужно использовать стороннюю библиотеку(Boost.Multiprecision)?

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

Ты с упрямостью самого тупого барана пытаешься добиться подтверждения своего выбора, но тебе 48 раз уже написали:

поэтому ничего сверх double тебе и не нужно, и, более того, ничего не даст. Кроме тормозов и неудобства.

Но ты продолжаешь тупить и не читаешь/не понимаешь то, что тебе пишут.

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

Ну, например, да. Ещё можешь взять процессор с аппаратной поддержкой десятичной арифметики. В IBM System z, кажется, такие используются.

i-rinat ★★★★★
()
Ответ на: комментарий от yyk

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

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

Но я хочу решить ее с использованием чисел с фиксированной точкой. И в этом и был вопрос

Это тебе НИЧЕГО не даст, ибо тебе точно так-же придётся учитывать накопление ошибки и сравнение через вычитание. В этом и был неоднократный ответ.

Но если ты его тоже уяснил, то зачем тебе заниматься сексом в противогазе, стоя в гамаке на лыжах?

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

Это тебе НИЧЕГО не даст, ибо тебе точно так-же придётся учитывать накопление ошибки и сравнение через вычитание

Ты как понимаю Boost.Multiprecision не использовал.

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

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

rumgot ★★★★★
() автор топика
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от rumgot

Смотри куда хочешь и говори что хочешь - кому есть дело до слов того, кто ни в дугу не понимает ни в числа, ни в их представления, ни в погрешности вычислений, игнорирует советы других (да, не мои) и хочет «чтобы было красиво»?

Интересно, это сейчас все прогеры такие? «А другого глобуса у вас нет?...»

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

Ты зашел в тему и начал как пьяное быдло. Не дал ни одного сообщения по делу. Одни оскорбления. Твое представление обо мне, как и другие твои фантазии об окружающем мире реальностью не станут оттого, что ты их здесь напишешь. Если ты так легко раздражаешься от простых вопросов и получаешь удовлетворение оттого, что можешь безответственно и безнаказанно строчить оскорбления - ок, но лучше обратись к специалисту.

rumgot ★★★★★
() автор топика
Последнее исправление: rumgot (всего исправлений: 2)
Ответ на: комментарий от rumgot

А ты, кисо, технарь или кисейная барышня, что от малейшей грубости теряешь связь с реальностью, перестаёшь понимать то, что до тебя пытаются донести и падаешь в обморок?

Ладно, последний раз: ты хоть сам себе можешь объяснить, зачем тебе что-то иное, кроме double, если его точности (разрядности) достаточно? При этом забей на все причины, которые ты не сможешь выразить кодом.

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

А ты, кисо, технарь или кисейная барышня, что от малейшей грубости теряешь связь с реальностью

Я предпочитаю профессиональную уважительную манеру общения. А лексику «четких технарей» я оставлю таким же «мастерам своего дела»(на словах конечно).

Ладно, последний раз

Царь соизволил милость явить. Ты действительно так зациклен на себе, что думаешь, мол твоего высокого мнения я жду, как утреннего солнца? Предлагаю закончить на этом.

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

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

Нет, я действительно не понимаю: ты чего-то не договариваешь или чего-то не понимаешь, что цепляешься к чему угодно, лишь бы не принимать тот простой факт, о котором тебе другие говорили и не раз - тебе достаточно выше крыши простых double.

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

Но ты продолжаешь корчить из себя оскорблённое благородство - твоё право.

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

Ты как назойливая муха. Тебе прямым текстом говорю: я не считаю тебя специалистом, достойным давать советы. Мнение нормальных людей я выслушал и принял к сведению. Твое же мнение мне не интересно. Не позорься, мне плевать, что ты там думаешь про числа, точность и мою тему.

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

И при проверке их коллинеарности (проверка на равенство частных от деления составляющих координат векторов друг на друга (x1/x2==y1/y2 ?))

Это не решение всей проблемы, а всего лишь замечание, но тем не менее:

// Альтернативный способ проверки на коллинеарность (без операций деления)
v1   = ( x1, y1)
v2   = ( x2, y2)
perp = (-y1, x1) // перпендикуляр к v1
// векторы коллинеарны, если:
dot(perp, v2) == 0
// т.е.
(x1 * y2 - x2 * y1) == 0

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