LINUX.ORG.RU

Метапрограммирование - проблемы и пути их решения.

 , ,


12

6

Пичал я тут на днях токенайзел для C++-кода, но всё это меня добило я решил поделится.

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

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

Чтобы не быть голословным пишем что-то типа

constexpr uint64_t f(uint64_t a, uint64_t b) {
  return a + b; 
}
Всё ок, но пишем что-то сложнее, аля:

uint64_t m[] = {0, 1, 2, 3, 4};
constexpr uint64_t f(uint64_t a, uint64_t b) {
  return m[a] + m[b]; 
}

Бида( или это моё неосиляторство плюсов?), дак зачем они запилили эту фичу, если она может лишь галимую примитивщину? Шаблоны ещё ущербней. В чем приемущество? Зачем?

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

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

У меня есть 3 пути: терпеть, пилить свой язык и конпелятор самому( что долго и нудно) и ваш совет.

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

В Тейлоре от делений я бы увернулся, введя глобальную табличку обратных факториалов, ТС кстати это сообразил;-)

у меня деления только в компайл-тайме

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

это только на первый взгляд. IRL с ними хлопот куда как больше.

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

впрочем, я достаточно далек от этого всего

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

на интах (не gmp) будут почти те же проблемы, за редкими и неочевидными исключениями, которые в данной задаче роли не играют

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

скажем, если у нас есть одномерное уравнение теплопроводности, у которого фронт «волны» оказывается экспонентой x_{n+1}=1/4 * x_n, то после скажем 32 шагов 64-битный целый дойдет до значений, где фронт волны будет обрываться и не идти дальше

тут можно применить dithering, в смысле один раз в несколько шагов делать округление в целочисленной арифметике в другую сторону (т.е. скажем температуры ...,1,1,1,3,1,1,1,... перейдут в ...,1,1,2,1,2,1,1,...)

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

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

проблема изменения энергии это проблема округления - есть изменение энергии - есть округление. Если использовать fractional представление числел в виде (a/b) и только операции которые могут работать над полем рациональных чисел без округления, то данное решение уйдёт от данной проблемы, однако далеко не все задачи представимы в таком виде.

Так вот, зато целочисленное решение полностью спасает на от проблемы a+b=a, если a<<b и a/c+b/c!=(a+b)/c и прочих тому подобных.

тут можно применить dithering, в смысле один раз в несколько шагов делать округление в целочисленной арифметике в другую сторону (т.е. скажем температуры ...,1,1,1,3,1,1,1,... перейдут в ...,1,1,2,1,2,1,1,...)

ровно тот же подход используется в группе сохраняющих структуру алгоритмов на floating-point.

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

дифур

посмотрел я твою портянку и понял идею: если f(φ) означает вектор a, повернутый вокруг вектора b на угол φ, то из геометрических соображений

f(φ+Δφ) — f(φ) = Δφ⋅ f(φ)×b + o(Δφ)

а дальше все просто

хорошая идея

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

ровно тот же подход используется в группе сохраняющих структуру алгоритмов на floating-point.

хм, а я то надеялся, что там че-то похитрее, чем dithering

впрочем, dithering тоже не особо простой — там надо потрудится и обеспечить, чтобы холмы, образовавшиеся в результате dithering-а, не стали расти

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

хм, а я то надеялся, что там че-то похитрее, чем dithering

в группе, а не во всех. Ну и скорее не округление, а алгоритм дающий ошибку в определенную сторону, например при использовании методов Рунге-Кутты используют «совместные» (не помню даже английскую терминологию) генерирующие матрицы, напр Lobatto-A Lobatto-B в этом случае ошибки компенсируют др. друга. Этот подход используется даже в алгоритмах базирующихся на других методах.

А так алгоритмов много: проективные - после каждого шага мы возвращаемся на траекторию с «правильной» энергией (тут есть несколько подметодов со своими свойствами), разные методы замены переменных, методы разложения уравниние в B-Series (Butcher) ну и более сложные методы, которые я даже не осилил запомнить, использующие симплектическую структуру, симметрии, различные математические объекты, которые можно построить для таких систем. Всё это сдобрено кучей дополнительных подходов, которые должны соблюдаться, чтобы уменьшить ошибку вплоть до учета ошибок операций с плавающей точкой (таких как compensated summation).

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

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

С чего бы это? Та же интервальная арифметика и то же накопление ошибок.

целочисленная_арифметка != интервальная_арифметика, см. хинт в Метапрограммирование - проблемы и пути их решения. (комментарий)

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

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

я от всего этого далек

если есть какие-то яркие идеи, уже известные тебе — тогда пиши подробно

ну а иначе мне вполне достаточно обзорной инфы по вопросу (которую ты написал), так, чисто из любопытства

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

Ну я даже графики рисовал, глядел, считал, википедию курил - я хороший.

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

так что если ты накачаешься наркотой и получишь 20 тактов на требуемой точности, то я скажу «победителя не судят»... правда почему-то я все-таки существенно больше верю в чтение википедии и пейперов, чем в наркоту

ну и еще — в сам знаешь какой рашке бывают, по рассказам, конторы, где от программиста главное — не код, а дресс-код (около газпрома, по рассказам)

Я придумал стопицот способов, но так и не придумал чего-то, что требудет менее 1умножения на разряд.

подскажу — тейлор, но с дополнительными хитростями, обеспечивает — у меня на 30 (или даже 35, я точно не считал) двоичных разряда точности используется 16 умножений и 5 сложений

если расчехлить wxMaxim-у, то видимо можно избавится от 1 умножения, но мне влом, т.к. чувствую пейперов полно

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

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

Мы считаем что-то, но для этого нам надо нагородить тысячу кастылей на флоатах, а без них мы считать на этом желе не можем. Что мы будем делать? Нет, мы не будем придумывать то железо, которая хорошо будет это считать - мы будем дальше есть кактус и решать проблемы кастылестроительством.

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

А потом мы скажем, что суперхаккиллер1997 лох, ибо нихрена не понимает наших сложных штук, хотя 99% сложности в наших штуках - это кастыли.

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

Белка появился - вы мне так и не объяснили конкретно зачем вам делать пробелы между битиками.

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

Есть D-мерный массив, который эмулируется на основе одномерного. Т.е. пусть у нас (x,y) координаты элемента, а i - смещение от начала одномерного массива. Обычно i выглядит так:

0  1    2 ... Nx-1
Nx Nx+1 ..... 2*Nx-1
...

Надо делать так:

0  1  4  5   16 ...
2  3  6  7
8  9  12 13
10 11 14 15
...

Соответственно нужно быстро переводить i->(x,y), (x,y)->i, и вычислять смещения до ближайшего соседа от (x,y) в любую сторону.

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

Симплектическая структура это то, чтов физике называется интегралом (движения)? Всякие законы сохранения (импульса, энергии и пр)?

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

http://www.femto.com.ua/articles/part_2/3641.html

если под законами сохранения понимать также, возможные траектории движения, например |R|==const для движения по сфере, то да. Возможно я упускаю некоторые доплнительные связи, но сейчас мне лень думать над этим.

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

Насколько я понял вики, d omega = 0 это как раз и есть интеграл движения.

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

Если же схема консервативна, то увидев что на тестах та же энергия сохраняется с машинной точностью, все кричат «алиллуйя» и идут квасить, поскольку для борьбы с ошибкой округления существует double;-)

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

он не интервальный

float интервальный. Однако интервал там не такой, как ты хочешь, а фиксированный. Он составляет ±½ единицы младшего разряда.

«от 3 до 4» + «от -3 до -4» = «от -1 до +1», что в иеее представления не имеет

интервалы проходящие через ноль всегда неоднозначны, ибо ноль в float представлен с бесконечной точностью. Это особое число. Что касается обычных чисел, то всё работает: x+y работает правильно, если x==y, тогда погрешность автоматически удваивается, т.к. само число удваивается. Потому мантисса сдвигается вправо, и младший разряд автоматически удваивается. При сложении разных чисел, большой интервал автоматически съедает малый, как оно и должно быть.

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

я не очень понимаю, зачем тебе нужна истинная интервальная арифметика? Если ты рассчитываешь какую-то схему, где номиналы заданы с допуском, то что тебе мешает представлять номинал двумя float'ами? А если тебе нужно просто считать с _заданной_ точностью, то почему-бы тебе просто не взять float нужного размера?

Использовать для всего этого int'ы неудобно, ибо в них погрешность абсолютная, а в ТЗ обычно прописывают относительную. Т.о. int подойдёт лишь в тех немногих случаях, когда диапазон ВСЕХ значений жёстко ограничен между двумя степенями двойки.

Ну и кроме того, только на ассемблере получается хороший код, для работы с числами с фикс. точкой. Скажем в x86 ты сразу получаешь произведение двух _любых_ FixPoint, а вот в сишечке оно обрезается так, как если-бы точка была как в целых, и даже никаких данных о переполнении не получить, приходится для умножения 32х битных чисел множить 64х битные.

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

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

впрочем, я достаточно далек от этого всего

дык в float'ах почти вся борьба уже успешно завершена, а вот в int'ах тебе придётся всё делать с нуля. Даже если целевой CPU не умеет float, лучше всё равно пользоваться эмуляцией, ибо ВСЕ значения на тестировании не покроешь в принципе(или тестирование займёт непропорционально много времени).

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

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

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

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

ЧСХ те, что представимы, очень быстро приводят к километровым несократимым дробям. В этом нет смысла, в силу катастрофического замедления.

Так вот, зато целочисленное решение полностью спасает на от проблемы a+b=a, если a<<b

скорее b<<a. Так? Но целые решают эту проблему тогда, и только тогда, когда b≥1. И даже, если b>1, то всё равно возникает потеря точности: 100+1½-100 == 1, что на треть меньше истинного значения. Не кажется-ли тебе, что 33% это сильно дофига? Что-бы считать более-менее точно, то перед сложением тебе нужно сдвигать a,b влево, почти до максимума, потому считать, а потом сдвигать обратно и округлять. Float это всё делают автоматически.

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

А потом мы скажем, что суперхаккиллер1997 лох, ибо нихрена не понимает наших сложных штук, хотя 99% сложности в наших штуках - это кастыли.

так и скажем, не понимает. И это — печально. Проблема в том, что IRL величины задаются не точно, а в смеси с некоторой погрешностью, нравится тебе это, или нет. Т.е. рулетка даёт не 123мм, а 123 ЦЕЛЫХ миллиметра. IRL там ещё немного нецелых, причём непонятно сколько именно. Вот такие вот кривые числа и приходится считать. Если делать по твоему, то в КАЖДОЙ операции будет накапливаться ошибка, которая пришла ещё из измерений. Для этого-то и придумали float'ы, которые и используются повсеместно. Да, они не точные, но это не баг, а фича. Привыкни к мысли, что float — это не просто число, а комплекс числа, и его погрешности. Причём последняя имеет вполне определённый диапазон значений, хоть её конкретное значение и не определено.

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

ЧСХ те, что представимы, очень быстро приводят к километровым несократимым дробям. В этом нет смысла, в силу катастрофического замедления.

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

скорее b<<a. Так?

да конечно.

Но целые решают эту проблему тогда, и только тогда, когда b≥1. И даже, если b>1, то всё равно возникает потеря точности: 100+1½-100 == 1,

в правильно нормированных целых у тебя есть изкоробочная гарантия, что для всех значений попадающих в рабочий диапазон, все будет работать, так если ты хочешь точность 1e-18 то домнож на 1e18 и все будет работать (если не будет целочисленного переполнение (муа-ха-ха). В числах с плавающей точной, гарантий нет, это не говорит о том, что «все сломается», просто нужно осозновать что происходит и когда, нужно правильным образом составлять выражения и объяснить компилятору, что не нужно умничать и переставлять их. В целочисленных вычислениях нету потери точности точности на разность порядков при ненормированном сложении или сложении без под «буффера», и тем более при проблем с умножением.

Заметь, я не говорю, что нужно использовать целочисленные вычисления в расчетах, это бред сивой кобылы, несмотря на то, что они сглаживают часть проблем floating point, они убивают скорость работы (прощай научные расчеты и gamedev) и водят новые проблемы (привет переполнениям или gmp), они не решают проблему округления в физических задачах там, где она возникает. Единственное место для применения целочисленных расчетов на мой взгляд это финансовые расчеты, где нельзя терять точность величины, а не системы, и плевать на скорость, но я этим не занимался, возможно там есть свои проблемы.

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

float интервальный. Однако интервал там не такой, как ты хочешь, а фиксированный. Он составляет ±½ единицы младшего разряда.

очевидно, что это не правда в общем случае. И я думаю ты это сам понимаешь.

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

В природе не существует никаких многомерныых массивов.

В ущербанском матане есть такая абстракция, аля [n][n]. Как это выглядит вр еальном мире 0 ... n*n.

#define N 4
uint8_t mas[N][N][N];
typedef struct {
  uint8_t a, b, c;
} for_shit_t;

inline for_shit_t i_to_shit(uint64_t t) {
  for_shit_t ret;
  ret.a = (t & (N - 1));
  ret.b = ((t >> (__builtin_ctzll(N))) & (N - 1));
  ret.c = ((t >> (__builtin_ctzll(N) << 1)) & (N - 1));
  return ret;
}

inline uint64_t shit_to_i(uint8_t a, uint64_t b, uint64_t c) {
  uint8_t * ret = &mas[a][b][c]; 
  return (uint64_t)ret - (uint64_t)mas;
}

Это?

Гцц сделал щит_то_ай примерно так же, как я - я выпилил свой код. А писать для ай_то_щит в адресной арифметике дольше, чем в моей.

Это быстрее твой той байды из поста( я даже не понял, что ты хочешь сделать даже).

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

В природе не существует никаких многомерныых массивов

Скажите об этом людям, работающим в екселе например;-)

я даже не понял, что ты хочешь сделать даже

А Вы попробуйте понять. Или погуглите «фрактал Лебега».

ЯННП в Вашем коде.

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

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

дык float как раз и есть рациональная дробь, когда числитель — целое число, а знаменатель — степень двойки. Всё логично и применимо.

в правильно нормированных целых у тебя есть изкоробочная гарантия, что для всех значений попадающих в рабочий диапазон, все будет работать, так если ты хочешь точность 1e-18 то домнож на 1e18 и все будет работать

будет, если не вылезет. Ни влево, ни в право. причём вылезать оно будет в зависимости от величины, а величина может быть разной.

В числах с плавающей точной, гарантий нет

почему «нет»? У тебя есть гарантия, что результат будет в вполне определённом интервале, т.е. истинный результат будет находится внутри круга определённого радиуса и с определённым центром. А что до неточности, то на практике это не имеет значения, ибо во первых входные данные не точные (а значит в точных вычислениях нет смысла), а во вторых, ты _всегда_ можешь определить максимальную погрешность результата. Если она заведомо меньше неточности из-за неточности на входе, то смысла в абсолютно точных расчётах нет абсолютно. Только-что процессор греть.

они убивают скорость работы

это мелочь. Скорость можно купить. Проблема в точности, если ты не умеешь с ней работать, тебе никакие 1e18 не помогут. А если умеешь, то сойдёт и float, причём результат будет НЕ хуже, а лучше.

Единственное место для применения целочисленных расчетов на мой взгляд это финансовые расчеты, где нельзя терять точность величины, а не системы, и плевать на скорость, но я этим не занимался, возможно там есть свои проблемы.

ЕМНИП, intel давала гарантию, что её i8087 не ошибается в целых НИКОГДА, если они за 2⁶⁴ не вылезают. Т.е. FPU подойдёт и для абсолютно точных вычислений.

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

Нет, твоё мышление не целочисленное.

У тебя есть измерительные приборы - если их минимальное значение милиметр, то насколько он реально отклоняется от этих 123 - тебе похрен, ибо ты этого не ведаешь и ведать не можешь.

Ты не знаешь какую погрешность даёт тебе рулетка, да и это не важно, важно лишь то, что это 123одинаковых единицы расстояния и похрен какое это расстояние. Хоть 1.1 милиметра, хоть 1.000001, хоть 2.35484958 - это похрен.

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

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

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

Такое поведение( без округления) реализуется для uint64_t чем-то типа деления на 10, когда результат приблизился к последним битам.

Флоат - это банальный целочисленный тип, который огругляется на пороге который в нём хранится.

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

float интервальный. Однако интервал там не такой, как ты хочешь, а фиксированный. Он составляет ±½ единицы младшего разряда.

очевидно, что это не правда в общем случае. И я думаю ты это сам понимаешь.

про что именно ты говоришь? Да, в операциях погрешность выше, но в даташитах она прописана.

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

i_to_shit() - переводит ай в индекс для трёхмерного массива.

shit_to_i() - переводит индекс 3-хмерного массива в ай.

Для 3-хмерных массивов с ребром в степень двойки - вычисляет это за 1-2такта.

А Вы попробуйте понять. Или погуглите «фрактал Лебега».

Я понял, что ваша проблема заключается в том, что вы юзаете вместо mas[n][n][n] mas[n*n*n], и вам надо уметь переводить индекс для первого массива во второй и наоборот, аля:

mas[4][4][4];
mas[3][3][3] = 123;
type_of_mas_elem * ptr = mas;//теперь ptr[1] == mas[0][0][1], а ptr[63] == mas[3][3][3];

Либо я не понял, и я зафейлил, то объясните дебилушке подробней.

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

Я понял, что ваша проблема заключается в том, что вы юзаете вместо mas[n][n][n] mas[n*n*n], и вам надо уметь переводить индекс для первого массива во второй и наоборот

Да, это правильно. И еще искать соседей;-)

Но наш массив лежит в куче, и его размеры на момент компиляции неизвестны. Большой он...

Точнее, есть два варианта - когда размеры массива извсетсны в компайлтайм, и когда неизвестны.

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

Нет, твоё мышление не целочисленное.

мышление тут не при чём.

У тебя есть измерительные приборы - если их минимальное значение милиметр, то насколько он реально отклоняется от этих 123 - тебе похрен, ибо ты этого не ведаешь и ведать не можешь.

ты упорот, чуть менее, чем полностью. Погрешность КИПов составляет обычно ½ деления в обе стороны. Т.е. если стрелка на 17, а соседние деления 16 и 18, то истинное значение 17±½. При этом стрелка должна находится во второй, или в третей части шкалы. Это общее правило, конкретика может отличаться, и подробно расписана в документации к КИПу.

Ты не знаешь какую погрешность даёт тебе рулетка

знаю.

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

это фейл КИПа. Причём это не баг, а документированная фича.

Флоаты придумали не для этого

может ты всё-же учебник почитаешь? Хоть какой-нить?

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

Какого размера(примерно) у вас массивы? Я придумаю пацанский обход для него с моей системой.

Ну и примерно опишите то, что вы делаете.

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

1024x1024x1024

Но бывают и двумерные случаи, тогда больше.

Ну вот решаем мы у-е теплопроводности, а данные лежат по фракталу лебега. Задачи я уже написал - i->(x,y,...), (x,y,...)->i и поиск соседа (известно i для (x,y) надо найти i для (x+-1,y,...), для (x,y+-1, ...) и т.д.).

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

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

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

ты упорот, чуть менее, чем полностью. Погрешность КИПов составляет обычно ½ деления в обе стороны. Т.е. если стрелка на 17, а соседние деления 16 и 18, то истинное значение 17±½. При этом стрелка должна находится во второй, или в третей части шкалы. Это общее правило, конкретика может отличаться, и подробно расписана в документации к КИПу.

Ты несёшь такую херню, я просто поражаюсь. У меня значение деления 1 и погрешность 1 - гениально.

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

знаю.

Ты знаешь лишь разброс, аля либо пол милиметра, либо полтора, либо что-то между ними.

Идиот = 0.5, вменяемый челове 1.5 - ты кто? Ты же знаешь погрешность - ну вот ты с шансом 50% идиот - гениеально.

это фейл КИПа. Причём это не баг, а документированная фича.

бла-бла.

может ты всё-же учебник почитаешь? Хоть какой-нить?

Может перестанешь нести херню? Мне твоя точность +-50% от деления говорит лишь о том, что у тебя плохо с мышлением.

Ну и да, как я тебе уже говорил без разницы какая погрешность, главное переодичность. Если на рулетке деление равно 0.5милиметра - я просто почитаю и умножу результат на 2 - мне это не помешает. Будет она 10000милиметров - я поделю на 10к.

Ты несёшь абсалютно бессмыслецу, как ты её нёс во всех темах.

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

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

для сложения погрешность почти равна ±½, для умножения она несколько выше ЕМНИП. Погрешность всяких синусов и логарифмов составляет ЕМНИП 2..4 бита, и держится в жёстких документированных рамках.

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

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

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

давай ты мне покажешь пример либы где это сделано и разойдёмся.

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

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

реальная точность (она называется абсолютной) величины x, составляет ±.00000011920928955078125 часть этой величины. Для float.

Может перестанешь нести херню? Мне твоя точность +-50% от деления говорит лишь о том, что у тебя плохо с мышлением.

иди, почитай википедию: http://ru.wikipedia.org/wiki/Класс_точности

Ъ>за погрешность s прибора принимают половину цены его наименьшего деления.

Ты несёшь абсалютно бессмыслецу, как ты её нёс во всех темах.

мир вообще бессмысленный. Что делать?..

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

Дак для 1024x1024x1024 мои функции дают результат за пару тактов.

У вас (х1, x2, x3), где:

x1 - это множитель для размерности 1024*1024. x2 - это множитель для размерности 1024. х3 - это единицы, который дабовляются тупо.

Т.е. елемент [1000][1000][1000] будет (1000*1024*1024)+(1000*1024)+1000.

Это делает за lea((1000*1024*1024), (1000*1024), 1000). Сдвиг и леа.

Обратно - это просто взять по маскe (1024-1) еденицы х3, потом сдвинуть это на 1024 и о5 взять по маске х2, а потом так же х1. Это чуть дольше, но тоже нереально быстро.

Я понял - вы ищете соседа в Nмерном пространстве и для этого вам нужен 3-хмерный индекс. И потом вы их разименовываете? Если это там мне жалко ваш кеш и тлбешечку.

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

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

давай ты мне покажешь пример либы где это сделано и разойдёмся.

здесь http://en.wikipedia.org/wiki/IEEE_floating_point нету? Я просто давно не вдавался в детали, но раньше именно там всё и было.

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

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

Обычно мирятся используя известные методы и тестирование.

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

реальная точность (она называется абсолютной) величины x, составляет ±.00000011920928955078125 часть этой величины. Для float.

Нет никакой реальной точности у флоата. Флоат устроен так, что его значение не поплывёт пока оно либо лёгкое для представления, либо сложно, но влезает в биты.

Никаких +- - забудь об этой детсадовской хрени, как и своих глупых заглушках, аля устройство памяти в ОС/х86, либо УБ головного мозга( аля тот пример с УБ в умножении, когда поведение умножения на х86 опеределено и спокойно можно умножать 64бита на 64бита и получать 128битный результат, то же самое +-).

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

Ъ>за погрешность s прибора принимают половину цены его наименьшего деления.

Что ты мне этим хочешь сказать? Какая нахрен цена деления, если суть в самих делениях и переодичности результат.

Твои ущербности - это детсадовские основы переодичной шкалы.

мир вообще бессмысленный. Что делать?..

Всё смысленно, кроме выхлопа некоторых личностей.

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

нету, нормального решения нигде нету

решение с float вполне себе даёт более чем достаточную точность в любом практическом диапазоне.

и оно будет только если ты будешь явно таскать инфу о погрешности по всей программе, такое никому не нужно :)

ну говорю-же, в float оно неявно и таскается. Просто надо помнить, что во первых НЁХ есть, во вторых нужно уметь её считать. А это, на самом деле, совсем не сложно. ИМХО хватит средней школы.

Обычно мирятся используя известные методы и тестирование.

кто-то спорит с этим? Ошибка совсем не всегда лежит на виду, часто она замаскирована, и незаметна. Но никакой магии тут нет.

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

Что ты мне этим хочешь сказать? Какая нахрен цена деления, если суть в самих делениях и переодичности результат.

если рулетка показала 1234, то результат равен 1234±½. Просто запомни этот факт, если понять его ты не в состоянии.

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

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

решение с float вполне себе даёт более чем достаточную точность в любом практическом диапазоне.

каноническое решение на double не дает достаточной точности практически во всех задачах с которыми мне надо сталкиваться (даже элементарных типа волчка Чаплыгина).

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

решение на double не дает достаточной точности

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

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