LINUX.ORG.RU

рекурсия и итерация

 итерация,


1

3

Приветствую всех.
Вопрос мой довольно праздный, и возможно кому-то покажется бесполезным. Тем не менее. Не кажется ли вам, что то что сейчас понимается под этими 2 терминами несколько не соответствует действительности. Вот что я имею в виду. У нас есть рекурсивный процесс, он интуитивно понятен на примерах трельяжа, стихотворения «у попа была собака» и пр. В программировании он может быть выражен 2-мя способами: с помощью итерациии и с помощью того, что принято называть рекурсией
На концептуальном уровне, это, безусловно, неверно, поскольку мы имеем 1 процесс и 2 способа его реализации, и называть способ реализации процесса самим процессом не совсем правильно. Таким образом, я хочу сказать, что выражение «рекурсивная реализация алгоритма» значит то же, что «рекурсивная реализация рекурсивного алгоритма» - бессмысленный набор слов, и, при этом, сама реализация, собственно не имеет ничего общего с рекурсией
Хотелось бы попросить воздержаться от постов вроде «Ты не знаешь язык X и математическую теорию Y, поэтому ты чмо». Если то, что я написал кажется вам глупостью, просто проходите мимо.
Итак, ваши мнения, Господа.

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

И что, нельзя это запоминание реализовать в цикле?

нет. В итеративном цикле — нельзя. «Итеративный», это такой, где n+1 выражается *только* через n. А рекурсивный — через (в общем случае) — *всё*. В частности при обходе дерева твой путь зависит от того, где ты *уже* был. второй раз туда же ходить не нужно. Потому нужно на тех ходах ставить крестики. Тем и отличается рекурсия от итерации, в итерации ты просто последовательно перебираешь множество.

Конечно можно сделать в цикле, сделав эмуляцию стека возвратов например массивом. Для бинарного дерева глубиной h достаточно всего h бит.

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

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

А кто запрещает прыгнуть назад при переборе?

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

нет. В итеративном цикле — нельзя. «Итеративный», это такой, где n+1 выражается *только* через n. А рекурсивный — через (в общем случае) — *всё*. В частности при обходе дерева твой путь зависит от того, где ты *уже* был. второй раз туда же ходить не нужно. Потому нужно на тех ходах ставить крестики. Тем и отличается рекурсия от итерации, в итерации ты просто последовательно перебираешь множество.

Тогда ответь на следующие вопросы:

1) поиск в глубину итеративен или рекурсивен?

2) поиск в ширину итеративен или рекурсивен?

3) алгоритм Флойда-Уоршелла итеративен или рекурсивен?

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

К чему я это все спрашиваю? К тому, что я любой алгоритм могу вывернуть и в рекурсию, и в итеративный процесс.

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

К тому, что я любой алгоритм могу вывернуть и в рекурсию, и в итеративный процесс.

Это собственно и подтверждает мою мысль.

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

в итерации ты просто последовательно перебираешь множество.

последовательный перебор множества ты тоже можешь представить «рекурсивной» записью.

(define tst (lambda(lst) (if (not (null? lst)) (do-staff))))

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

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

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

Ну, я назову всю историю состояний рекурсивного процесса просто состоянием и процесс превратится в итеративный по определению.

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

Нет, не превратиться. Подумай о степени роста твоего «состояния».

Вы имеете в виду рост на реальной машине? Если не на машине а вообще - то процесс линейный и бесконечный, это даже не рост собственно, ну и что?

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

Нет, не превратиться. Подумай о степени роста твоего «состояния».

И что? Теперь любой прожорливый к памяти алгоритм будем называть от этого рекурсивным?

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

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

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

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

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

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

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

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

Я осмелюсь даже больше сказать: любые итеративные вычисления являются выражением рекурсии.

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

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

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

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

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

А кто запрещает прыгнуть назад при переборе?

то, что в одном числе(счётчике итераций) хранится одно число. Потому прыгать ты можешь только вперёд, и только на одну итерацию. Иначе это уже не итерации.

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

Тогда ответь на следующие вопросы:

у тебя собеседование на носу что-ли? А я значит бесплатный репетитор для тебя?

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

К тому, что я любой алгоритм могу вывернуть и в рекурсию, и в итеративный процесс.

«итеративный» он будет лишь при наличии дополнительной памяти неизвестного объёма. Потому в кавычках. Без кавычек итеративен лишь алгоритм требующий O(1) памяти.

Естественно стек можно юзать какой угодно, не обязательно тот, что в CPU на esp.

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

у тебя собеседование на носу что-ли? А я значит бесплатный репетитор для тебя?

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

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

«итеративный» он будет лишь при наличии дополнительной памяти неизвестного объёма. Потому в кавычках. Без кавычек итеративен лишь алгоритм требующий O(1) памяти.

Вот тут уже хотя бы что-то стало проясняться.

Правильно ли я понимаю, что любой алгоритми, требующий больше O(1) памяти, уже будет рекурсивным?

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

в итерации ты просто последовательно перебираешь множество.

последовательный перебор множества ты тоже можешь представить «рекурсивной» записью.

конечно. Ибо итерация — частный случай рекурсии.

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

о чем вы тут вообще оба? Итерация - это тоже рекурсия.

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

Ты путаешь понятие рекурсивного алгоритма с понятием рекурсивного процесса. Тебе тут уже объяснили.

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

А в двух счетчиках сколько хранится чисел? А в 100?

в C счётчиках хранится O(C) === O(1) чисел.

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

У тебя какое-то очень извращенное понятие об итерации.

у Кнута и в SICP тоже самое. Но вы же не читали...

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

Правильно ли я понимаю, что любой алгоритми, требующий больше O(1) памяти, уже будет рекурсивным?

нет, неправильно. Конечно любой алгоритм можно переписать так, что-бы на n шагов он пожрал O(n!) памяти. Дурное дело не хитрое.

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

Ты путаешь понятие рекурсивного алгоритма с понятием рекурсивного процесса. Тебе тут уже объяснили.

О рекурсивных процессах, кажется, никто не говорил, нет?

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

нет, неправильно. Конечно любой алгоритм можно переписать так, что-бы на n шагов он пожрал O(n!) памяти. Дурное дело не хитрое.

Что и требовалось доказать =)

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

у Кнута и в SICP тоже самое. Но вы же не читали...

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

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

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

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

нет, неправильно. Конечно любой алгоритм можно переписать так, что-бы на n шагов он пожрал O(n!) памяти. Дурное дело не хитрое.

Что и требовалось доказать

поймать меня хотел что-ли? Ну не получилось...

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

то, что в одном числе(счётчике итераций) хранится одно число. Потому прыгать ты можешь только вперёд, и только на одну итерацию. Иначе это уже не итерации.

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

лениво искать.

вот вику почитай: http://ru.wikipedia.org/wiki/Итерация

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

поймать меня хотел что-ли? Ну не получилось...

Поймать?

Ты писал, что

В смысле? Всегда любую рекурсию можно переписать без оной.

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

А потом сам же пишешь, что можно.

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

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

А потом сам же пишешь, что можно.

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

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

Тут всё зависит от числа вариантов m и шагов n. Если m^n небольшое число, то нет никакой нужды в рекурсии, и можно просто перебрать. Но вот я сейчас перебираю 196627050475552913618075908526912116283103450944214766927315415537966391196809 вариантов — fail. Сейчас пойду спать, и если решения не найдётся, придётся применить рекурсию, вместо итерации. Проблема в том, что я не знаю, сколько есть решений, но очевидно, что в первом миллиарде вариантов решений нет(уже перебрал), потому придётся наверное применить рекурсию, что-бы более экономно выбирать варианты. Рекурсия более «умная», т.к. я могу отсекать те пути, по которым я уже прошёл. Думаю, затратив несколько гигабайт памяти и несколько часов, я смогу просмотреть всё пространство решений, на что в итеративном варианте не хватит не только моей жизни, но и жизни всей вселенной...

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

Где там написано, что итерация не может выделять память?

а зачем для итерации дополнительная память? Есть формула для вычисления след. числа, что ещё надо? Ну вот например для вычисления 5! вовсе не обязательно вычислять 5,4,3,2,1 и потом перемножать, можно сразу умножать, потому достаточно памяти всего на 2 числа. Но если ты обходишь дерево, тебе нужно по одному биту на каждый поворот(для бинарного дерева, для тернарного уже 2 бита, точнее log2(3)), а таких поворотов столько, сколько высота дерева, а высота вообще говоря неизвестна, и может быть какой угодно.

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

а зачем для итерации дополнительная память

То есть код

for(i=0; i < seq.length(); i++)
{
   if(seq[i] > 10) res.append(seq[i);
}

не является итерацией? Ведь он выделяет память

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

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

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

а что же она должна вычислять-то?

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

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

У тебя не сама итерация выделяет память, а код внутри нее.

охлол. Этот код и есть итерация, если что.

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

Вот этот код, тогда тоже итерация? :

Number ack(m, n)
{
   vector<Number> s;
   while(m!=0 || s.length()>0) {
      if(n==0) m--;
      else {
         s.append(m);
         n = n--;
      }
      if(m==0 && s.length() > 0) {
         m=s.pop();
         m--;
         n = n++;
      }
   }
   return n+1;
}
monk ★★★★★
()
Ответ на: комментарий от qulinxao

действие(изменение окружения) не есть число.

а есть ещё что-то? Что-то кроме комбинации чисел? Может есть любовь, радость? Ты рассказывай, а то я же не в курсе.

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

не является итерацией?

это итерация к которой ты прилепил выделение памяти. Но оно тут не нужно, ибо очевидно, что алгоритму нужно seq.length() памяти, и внутри цикла это предопределённая константа. Т.е. выделение памяти является инвариантным для тела цикла.

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

Да, факториал выше не является истинной рекурсией. Но он являлся-бы, если-бы мне было нужно хранить не все числа, а только некоторые. Или все, но НУЖНО.

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

Он просто накапливает результат. Каждая итерация не зависит от следующих итераций. В рекурсивном же процессе у тебя будет «стек» промежуточных значений. И именно из них будет состоять память, про которую тебе тут говорят.

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

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

ну и где я говорил, что «не может быть графом, а только целое число от 3 до 7»?

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

Этот код и есть итерация, если что.

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

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

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

Тогда можно и в обходе бинарного дерева сразу выделить кусок памяти размером log_2(N).

Тогда обход дерева станет итеративным?

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

n = n--;

Завязывай с тяжелыми наркотиками.

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

Прочти уже SICP.

(define (factorial n)
   (if (= n 1)
       1
       (* n (factorial (- n 1)))))

vs

(define (factorial n)
   (fact-iter 1 1 n))

 (define (fact-iter product counter max-count)
   (if (> counter max-count)
       product
       (fact-iter (* counter product)
                  (+ counter 1)
                  max-count)))

Или же

(define (fib n)
   (cond ((= n 0) 0)
         ((= n 1) 1)
         (else (+ (fib (- n 1))
                  (fib (- n 2))))))

vs

(define (fib n)
   (fib-iter 1 0 n))

 (define (fib-iter a b count)
   (if (= count 0)
       b
       (fib-iter (+ a b) a (- count 1))))

Неужели непонятна разница? Развели тут...

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

Это рекурсивный процесс.

В чём тогда отличие рекурсия и итерация (комментарий) от рекурсия и итерация (комментарий) ?

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

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

Все уже говорилось. Читай SICP, может дойдет.

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

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

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

Тогда можно и в обходе бинарного дерева сразу выделить кусок памяти размером log_2(N).

да, только не log2(N), а некое log2(N)<= h <= N.

Тогда обход дерева станет итеративным?

безусловно. Вот только нужно выделить либо N памяти, а это вполне может быть и 100Гб, либо обходить всё дерево перед каждым шагом, что-бы узнать текущее значение h. Естественно это можно, и не сложно, вот только работать оно будет медленнее простого списка, а памяти жрать будет больше.

Потому на практике такую итеративную замену никто не использует. А используют машинный стек + машинозависимые костыли для ограничения h + рекурсивный алгоритм обхода на аппаратном стеке.

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

Неужели непонятна разница? Развели тут...

ну ты правильно на SICP сослался, там есть хорошие и наглядные картинки как раз на эту тему. И объяснение вполне понятное. И ещё и по-русски. Что сразу на ЛОР тащить своё неосиляторство?

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

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

Почему res в

vector<Number> res;
for(i=0; i < seq.length(); i++)
{
   if(seq[i] > 10) res.append(seq[i);
}
ты не считаешь стеком, а s с тем же типом в

vector<Number> s;
while(m!=0 || s.length()>0) {
   if(n==0) m--;
   else {
      s.append(m);
      n = n--;
   }
   if(m==0 && s.length() > 0) {
      m=s.pop();
      m--;
      n = n++;
   }
}

считаешь?

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

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

вопрос «можно/неможно» никого не волнует. В рекурсивном алгоритме память никто заранее не выделяет, она сама выделяется. В итеративном она выделяется один раз. Естественно, любой итеративный алгоритм ты при желании можешь переписать как рекурсивный, выделяя память в любых количествах. Т.к. рекурсия — более общий случай. Обратное неверно, т.к. обход дерева или скажем qsort невозможно переписать в итеративный вид без велосипедной эмуляции стека возвратов для хранения контекстов.

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

Потому на практике такую итеративную замену никто не использует. А используют машинный стек...

В компиляторе Scheme стек совсем не машинный.

Вот только нужно выделить либо N памяти, а это вполне может быть и 100Гб,

Если аналог стека требует 100Гб, то машинный стек гарантировано упадёт с stack overflow.

А аналог я и на файл могу отобразить при очень большом «стеке».

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

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

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

В рекурсивном алгоритме память никто заранее не выделяет, она сама выделяется. В итеративном она выделяется один раз.

То есть

vector<Number> res;
for(i=0; i < seq.length(); i++)
{
   if(seq[i] > 10) res.append(seq[i);
}

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

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

Потому на практике такую итеративную замену никто не использует. А используют машинный стек...

В компиляторе Scheme стек совсем не машинный.

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

Если аналог стека требует 100Гб, то машинный стек гарантировано упадёт с stack overflow.

нет. Потому-что машинный стек не нужно _заранее_ выделять.

А аналог я и на файл могу отобразить при очень большом «стеке».

мне жаль твоих пользователей, которые плачут, когда твой 100Гб стек отображаются на их 64Гбый SSD. Особенно это печально, если из 100Гб нужно все 200 байт. Но ты же не думаешь, а «отображаешь»...

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

В твоем решении нет никаких промежуточных результатов, который ты хранишь в «стеке».

Что понимать под промежуточными результатами? Ну ладно...

vector<Number> res, s;
for(i=0; i < seq.length(); i++)
{
   if(seq[i] > 10) {
      if(!found_sorted(s), seq[i])
        res.append(seq[i);
      insert_sorted(s, seq[i]);
   }
}

s определённо промежуточная и динамически выделяемая. Это делает эту функцию рекурсивной?

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

Потому-что машинный стек не нужно _заранее_ выделять.

Не понял. Это спасёт при выполнении

int rec_sum(list s)
{
   if(s.next == NULL) return s.data;
   return s.data + rec_sum(s.next, i+1);
}
на списке в 100Гб?

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

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

А по-моему, от твоего тугоумия. Не я-то код писал.

Ну и не важно, какой там код, хороший или плохой.

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

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

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

Потому-что ИМХО если скорость/память не имеет значения, то самое важное — обеспечить максимально понятный код. Т.е. если алгоритм рекурсивный (от математиков), то его и надо записывать в виде рекурсии, как (define (factorial n)(if (= n 0) 1 (* n (factorial (- n 1))))), а не как-то иначе. потому-что преждевременная оптимизация == зло.

А если скорость/память значение имеет, то это совсем иная история.

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

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

Пишут, что здесь: http://www.getkahu.com/

Реализация Scheme под названием Racket

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

Это делает эту функцию рекурсивной?

У тебя тут нет функции. А процесс рекурсивным будет тогда, когда ты будешь использовать «раскручивать» ранее накопленные промежуточные результаты. Посмотри на схемки рекурсивных и итеративных процессов в SICP'е.

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

А на википедии написано: факториал — произведение всех натуральных чисел от 1 до n включительно.

Так что надо

(define (factorial n)
  (for/fold ([res 1]) ([i (in-range 1 n)])
    (* res i)))

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

О по-моему, от твоего тугоумия. Не я-то код писал.

при чём тут я? Тугодумие у тебя, если ты берёшь как пример чужой код, который не понимаешь. Но для тех, кто в танке, поясню: да, это НЕ итеративный алгоритм, ибо тут нет единого куска памяти, в котором ты работаешь. На каждой итерации выделяется свой фрейм памяти. Т.ч. алгоритм строго говоря рекурсивный, и не оптимальный. Это хорошо, ибо в таком виде он более понятен для разных жаба/php-обезьян. Сишник такую рекурсию разворачивает ещё в подкорке. Но тебе видимо не осмыслить программирование без std::append(), потому конструкция вроде *s++ для тебя «опасная» и «непонятная».

Ну и не важно, какой там код, хороший или плохой.

«хорошесть» кода зависит от ЯП и от задачи. Это явно не чистая сишечка, а какой-нить пхп. Там такое можно и нужно. Бантик красив на маленькой девочке, а на моей башке будет выглядеть нелепо. Всё зависит от контекста.

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

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

Пишут, что здесь: http://www.getkahu.com/ Реализация Scheme под названием Racket

покажи мне там скажем красно-чёрное дерево. Ну или qsort.

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

когда ты будешь использовать «раскручивать» ранее накопленные промежуточные результаты.

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

А ещё любая программа на FORTH'е...

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

А на википедии написано: факториал — произведение всех натуральных чисел от 1 до n включительно.

на самом деле у факториала есть несколько определений. Вот ещё одно:

n! <= (n-1)! * n; /n > 1/

n! <= 1; /n <= 1/

и это определение даёт более короткий, простой, и понятный код.Который не требует костылей типа for/fold и in-range.

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

Ты, баття, попой не верти, скажи прямо - ты все еще веришь, что стек «быстрее» произвольного массива?

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

покажи мне там скажем красно-чёрное дерево

внутри http://pre.racket-lang.org/racket/collects/mred/private/wx/common/rbtree.rkt

Для пользователей: http://planet.racket-lang.org/package-source/krhari/pfds.plt/1/4/planet-docs/...

qsort

С учётом того, что списки там чаще, чем вектора, там сортировка слиянием.

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

и это определение даёт более короткий, простой, и понятный код.

Зависит от стандартной библиотеки.

Или хочешь сказать, что

(define (fact n) (if (> n 1) (* (fact (- n 1)) n) 1))

Читается проще, чем

(define (fact n) (apply * (range 1 n)))

(если уж мы не про производительность, а про читаемость)?

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

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

Вот она, квинтэссенция маразма - рекурсивный значит выделяющий память. Браво!

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

Это хорошо, ибо в таком виде он более понятен для разных жаба/php-обезьян. Сишник такую рекурсию разворачивает ещё в подкорке. Но тебе видимо не осмыслить программирование без std::append(), потому конструкция вроде *s++ для тебя «опасная» и «непонятная».

Твой уровень аргументации просто фееричен. Не важно, хороший это код или плохой, важен твой ответ на вопрос, рекурсивен ли он.

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

Нет, конечно. Это «руками» организованная рекурсия.

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

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

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

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

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

Потому что в первом случае res не используется как стек, очевидно.

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

Рекурсивный алгоритм не просто работает со стеком - он работает со стеком вполне определенным образом. В частности рекурсивный алгоритм не имеет права выделять стекфреймы «по частям» или эмулировать подобное выделение «руками».

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

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

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

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

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

Сравните схемки:

рекурсивный процесс

итеративный процесс

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

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

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

sicp я прочитал, дальше что?

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

Есть тут рекурсия или нет, зависит от того, для чего ты используешь память. Просто для вычисления на итерации и перехода к следующей или же для самого процесса вычисления. Как-то так. ХЗ как уже формулировать.

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

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

естественно. Формула типа 2+2*2 является рекурсивной. Калькулятор тоже. Такое нельзя обработать итерацией, ибо нужно возвращаться, в данном случае нужно вернутся к сложению после умножения, что-бы получить правильный ответ 6.

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

ну тем более — ажно два машинных стека. К тому же, в ZX-Spectrum именно так калькулятор и был реализован (который в EEPROM с Basic) — два стека, один вверх рос, второй навстречу. В обычном, том, что по SP, хранились операторы вроде +,-,*,/, а во втором хранились числа. Обрабатывалось это всё рекурсивной функцией, какой-то INTxx, да, прерывание.

А ещё любая программа на FORTH'е...

да. И почти любая на сишечке (за исключением твоих хэлловорлдов конечно).

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

ты все еще веришь, что стек «быстрее» произвольного массива?

как он может быть не быстрее, если он железный, а массив == твой велосипед? Разве в твоём процессоре есть инструкция для записи в память по индексу с постдекриментом кроме push? А твои велосипеды в любом случае будут не быстрее.

И это несложно проверить при желании. Вот ты-бы чушь не порол, а взял-бы, и проверил. На своём процессоре.

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

внутри http://pre.racket-lang.org/racket/collects/mred/private/wx/common/rbtree.rkt

ну вот и сравни с любой сишной реализацией. Разница в скорости, как у ракеты «Союз» со светом. Да, ракета — быстрая. По сравнению с телегой.

С учётом того, что списки там чаще, чем вектора, там сортировка слиянием.

я знаю. Но многие задачи проще решаются «на месте», а не списком. Эта твоя ракета решает только половину задач? Ну ладно... Не обижайся только, что она никому не нужна.

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

Или хочешь сказать, что (define (fact n) (if (> n 1) (* (fact (- n 1)) n) 1)) Читается проще

Конечно проще, ибо смысл операций >,*,- мне знаком со школьной скамьи, а вот что значит операции apply и range я могу только догадываться.

Если для тебя не так, то поздравляю: у тебя lisp головного мозга.

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

как он может быть не быстрее, если он железный, а массив == твой велосипед?

Стек - это обычная область памяти, такая же, как и массив. По-этому стек ничуть не быстрее массива

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

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

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

ну вот и сравни с любой сишной реализацией. Разница в скорости, как у ракеты «Союз» со светом. Да, ракета — быстрая. По сравнению с телегой.

Не факт, на самом деле. Из-за сборщика мусора сишка как раз может оказаться тут телегой.

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

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

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

В сишке нет не то, что сборщика.

Ну да, нету. В этом и проблема - сборщик мусора это ракета, а сишковский маллок - телега.

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

как он может быть не быстрее, если он железный, а массив == твой велосипед?

Ну не быдло ли ты? Повторяю вопрос для недоумков: доступ к адресу по смещению от ESP чем-то отличается от доступа по, допустим, EAX?

Разве в твоём процессоре есть инструкция для записи в память по индексу с постдекриментом кроме push?

В моем процессоре, как и в любом, сделанном в последние 15 лет, push раскрывается в точно такую же последовательность uops, как и явный постдекремент регистра.

Вот ты-бы чушь не порол, а взял-бы, и проверил.

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

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

сишковский маллок - телега.

Это всего-лишь библиотека. Сборщик может быть сделан в другой библиотеки(Boehm GC, например). Для сишечки это не важно - как скажешь, так и будет. В то время как опыт пользования программ с GC говорит об их тормозах по сравнению с сишечными или плюсовыми.

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

Вот она, квинтэссенция маразма - рекурсивный значит выделяющий память. Браво!

если ты включишь голову, то поймёшь, что так и должно быть — рекурсивная функция, в отличие от итеративной, работает в персональном окружении(контексте), в этом и есть отличие. А как ты прыгаешь по коду — вопрос десятый, хоть call/ret, хоть loop. Да и ЯП тут не при чём.

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

Это хорошо, ибо в таком виде он более понятен для разных жаба/php-обезьян. Сишник такую рекурсию разворачивает ещё в подкорке. Но тебе видимо не осмыслить программирование без std::append(), потому конструкция вроде *s++ для тебя «опасная» и «непонятная».

Твой уровень аргументации просто фееричен. Не важно, хороший это код или плохой, важен твой ответ на вопрос, рекурсивен ли он.

тебе нечего возразить? Сливайся молча. Твоя фееричная демагогия никому не интересна. Как и твоё личное отношение лично ко мне.

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

sicp я прочитал, дальше что?

самое сложное: понять прочитанное.

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

А emulek говорит, что она есть.

здесь нет рекурсии. И здесь её нет:

void foo()
{
  foo();
}
это тоже самое — цикл, в котором выделяется память, которая никому не нужна. Разница в том, что этот быдлокод рухнет намного быстрее. Вот и всё.

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

Нет. В форте совсем другая модель вычислений.

The mistery of Yoda’s speech uncovered is: Just an old Forth programmer Yoda was

тоже самое, на самом деле. Такая модель очень часто используется внутри компиляторов и интерпретаторов. В железе её тоже часто реализуют. Просто очень непривычно выглядит первое время. Но привыкнуть несложно.

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

Стек - это обычная область памяти, такая же, как и массив. По-этому стек ничуть не быстрее массива

стек — обычная область памяти, согласен. Но для работы со стеком есть специальные команды и регистры. (sp,bp), позволяющие намного ускорить типичные операции стека(коих всего две — затолкать/вытолкать). Кроме того, есть специальная форма заталкивания/выталкивания регистра ip, которая не имеет аналога для простого массива. Потому сохранять можно не только данные, но и адреса кодов. Именно это и нужно при рекурсии, не просто вернуться, а запомнить _путь_, куда надо возвращаться. Велосипедить это всё указателями на функции или виртуальными функциями — жуткий геморрой и тормоза.

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

Не факт, на самом деле. Из-за сборщика мусора сишка как раз может оказаться тут телегой.

это если у тебя рукожопие.

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

Ну да, нету. В этом и проблема - сборщик мусора это ракета, а сишковский маллок - телега.

пиши свой СБИШ или возьми из ракеты. В чём проблема?

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

В моем процессоре, как и в любом, сделанном в последние 15 лет, push раскрывается в точно такую же последовательность uops, как и явный постдекремент регистра.

пруф будет?

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

тебе нечего возразить? Сливайся молча. Твоя фееричная демагогия никому не интересна. Как и твоё личное отношение лично ко мне.

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

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

Конечно проще, ибо смысл операций >,*,- мне знаком со школьной скамьи, а вот что значит операции apply и range я могу только догадываться.

А брейнфак тогда еще проще, ок.

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

Ты же отвечаешь не по существу

ответ по существу ты очевидно не осилил. А он выше уже был.

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

твои алгоритмы не имеют смысла. В математике это как сокращение дроби на ноль — доказать можно всё что угодно. Но зачем?

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

Ошибаешься, здесь рекурсия есть.

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

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

твои алгоритмы не имеют смысла. В математике это как сокращение дроби на ноль — доказать можно всё что угодно. Но зачем?

Алгоритмы? Мои? Был только сишный код, не мой, который ты так и не можешь толком отнести ни к рекурсивному, ни к интеративному.

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

пруф будет?

Замени везде в коде хрень вроде pushl %edi на movl 0(%esp), %edi; addl $1, %esp, и убедись, что разницы в производительности нет.

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

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

Конечно проще, ибо смысл операций >,*,- мне знаком со школьной скамьи, а вот что значит операции apply и range я могу только догадываться.

А брейнфак тогда еще проще, ок.

в некотором смысле — проще. Хотя писать на нём и сложнее. Он слишком простой, и тривиальная конструкция там занимает слишком много букв. Можно придумать простой естественный язык, ароде русского мата, но ты устанешь объяснять на этом языке что угодно сложнее «fuck off».

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

Алгоритмы? Мои? Был только сишный код, не мой, который ты так и не можешь толком отнести ни к рекурсивному, ни к интеративному.

дык мы про код говорим? Тогда я не знаю, что такое «рекурсивный код». Я знаю, что такое «рекурсивный алгоритм».

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

с т.з. алгоритма нет никакой разницы, что через что выражается. С т.з. алгоритма там безусловный jmp, и запись одного и того же числа в ячейки [sp], [sp-1], [sp-2],... Т.к. число только записывается, и ничего более, то совершенно не важно, что это за число.

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

Замени везде в коде хрень вроде pushl %edi на movl 0(%esp), %edi; addl $1, %esp, и убедись, что разницы в производительности нет.

на что мне менять call/ret?

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

то есть, movl %edi, 0(%esp)

это по любому длиннее(особенно с учётом inc/dec), а значит не влезет в кеш. Уже получишь тормоза, чисто из-за раздутого кода.

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

Можно придумать простой естественный язык, ароде русского мата, но ты устанешь объяснять на этом языке что угодно сложнее «fuck off».

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

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

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

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

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

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

на что мне менять call/ret?

Посмотри, как это сделано в ARM, где никаких call и ret нет в принципе.

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

нет.

там фишка в ныне ставшим модном «рефакторинге»

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

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

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

в компиляторах/интерпретаторах редко когда прямо манипулируют со стеком возвратов

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

Это не правда, ты значит не русский. Русским матом тривиально объясняется все. И ничего кроме него не нужно.

ТОЛЬКО русским матом ты не сможешь почти ничего КОНКРЕТНОГО объяснить. Кроме эмоций. Да, иногда этого достаточно. Но в этом случае можно и промолчать. Чё пи**ть попусту?

Алгоритмы — сплошная конкретика, и ты слишком много сил потратишь для изготовления конкретного float'а на BF'е. Попробуй, если не веришь. Нет, я знаю, что это возможно, и это не сложно. Но очень долго.

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

всё зависит от задачи. Иногда без этого никак, иногда это только мешает.

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

Ну как нет, если рекурсия по определению - код который вызывает себя.

ок. Это будем считать рекурсией кода. А моё определение (которое я выдрал из SICP) — определение рекурсивного алгоритма.

Так без вопросов?

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

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

Это все соплями по говну рассусоливание.

Ты как, успокоился?

Если да, то похмелись, и попытайся понять: Изначально я говорил про автоматические переменные в сишечке. Компилятор вовсе не обязательно их пихает в стек. В современных CPU amd64 и регистров полно, а регистры понятно быстрее(глупо с этим спорить, да). Туда и пихает.

Т.е. автоматические переменные в сишечке пихаются в регистры и/или в стек, в зависимости от того, что быстрее(в целевом CPU). Есть два следствия:

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

2. п1 это хорошо, но что плохо, эти переменные не разруливаются GC. Невозможно вернуть в пул то, чего там никогда не было. А регистров/стека там никогда не было. Потому в сишке нельзя сделать «полноценный» GC. Это плата за наличие быстрых переменных, которые в регистрах и/или в самой быстрой памяти (в стеке, для некоторых CPU).

Ты не обязан платить такую цену, если хочешь, делай ВСЕ свои переменные своим аллокатором. И они будут убираться твоим любимым GC. Как в любимой яве/пхп/сишарп.

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

На хрена вывод типа, если есть контекст.

ИМХО это фильтрует огромное количество глупых ошибок/опечаток. А в каком-нить пыхпыхе оно само всё сконвертит куда угодно, и потом будешь удивляться, как сумма 3х лестниц с 2я дорогами даёт 17 облаков и 3х лошадок. В сишечке нельзя складывать лестницы с дорогами в любом контексте.

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

В сишечке нельзя складывать лестницы с дорогами в любом контексте.

4.2. Кастуешь их обоих к голубям и складываешь.

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

В сишечке нельзя складывать лестницы с дорогами в любом контексте.

2+2.0 - сложение целого с вещественным. И не надо подводить под одно понятие динамическую и слабую типизацию. Сильная типизация в динамических языках как раз и нужна, чтобы не складывать 3 лестницы с 2я дорогами.

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

тоже самое, на самом деле.

Нет не то же самое. Ты просто не знаешь форта.

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

Но для работы со стеком есть специальные команды и регистры. (sp,bp), позволяющие намного ускорить типичные операции стека

Нет. Всмысле команды есть - но ничего они не ускорят, тем более «намного».

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

это если у тебя рукожопие.

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

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

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

Память в стеке выделяется точно так же, как в перемещающем GC.

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

п1 это хорошо, но что плохо, эти переменные не разруливаются GC. Невозможно вернуть в пул то, чего там никогда не было. А регистров/стека там никогда не было. Потому в сишке нельзя сделать «полноценный» GC. Это плата за наличие быстрых переменных, которые в регистрах и/или в самой быстрой памяти (в стеке, для некоторых CPU).

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

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

А ты забываешь про jit, который сам по себе не бесплатен и оправдывает себя не всегда. И да, llvm, пара плагинчиков для clang'а и соответствующий рантайм и будет у тебя ЛЮБОЙ GC. Вот только невостребован он в С и даже в С++, там немного другой подход к разработке - в Си в каждом проекте свой подход, в С++ - тоже, хотя и большинству проектов хватает подсчета ссылок(иногда вместе с детектором циклов) - shared_ptr и weak_ptr, в отличие от сборщиков, это позволяет хотя бы ресурсы различные вовремя отдавать и без всяких костыликов вроде finally.

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

А ты забываешь про jit

Джит никак не связан со сборщиком мусора.

И да, llvm, пара плагинчиков для clang'а и соответствующий рантайм и будет у тебя ЛЮБОЙ GC.

Не будет.

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

4.2. Кастуешь их обоих к голубям и складываешь.

для быдлокодера любой ЯП годен

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

2+2.0 - сложение целого с вещественным.

и что тут такого страшного? Это сложение вещественного и вещественного.

И не надо подводить под одно понятие динамическую и слабую типизацию.

типизация в сишечке не слабая, целое число без потерь преобразуется в вещественное. Целое — частный случай вещественного.

Сильная типизация в динамических языках как раз и нужна, чтобы не складывать 3 лестницы с 2я дорогами.

угу, потому-что если дорога выглядит как лестница, крякает как лестница, то это лестница. Т.ч. пишем к дороге метод view() и kru(), как в лестнице, и она становится лестницей. С которой мы и складываем другие лестницы, получая облака и крякающих лошадок.

А потом все рассказываем, какое C/C++ говно, потому-что там так нельзя. А типизация слабая, ибо число 2 является вещественным в контексте вещественных чисел. А почему не так-то? Разве теперь множество вещественных чисел уже не включает целые?

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

Разве теперь множество вещественных чисел уже не включает целые?

Не включает и никогда не включало. Целые числа - это классы эквивалентностей пар натуральных, вещественные числа - классы эквивалентностей фундаментальных последовательностей пар классов эквивалентностей троек натуральных.

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

Всмысле команды есть - но ничего они не ускорят, тем более «намного».

тогда представь мне аналоги команд push/pop и call/ret, и я проверю скорость работы твоих аналогов. Ну например для x86, 32 бита.

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

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

лови:

uint8_t *pool = NULL;
uint8_t *pool_ptr = NULL;

void super_init()
{
  pool = malloc(1048576U*1048576U);
  pool_ptr = pool;
}

void *super_malloc(size_t s)
{
  uint8_t *r = pool_ptr;
  pool_ptr += s;
  return (void*)r;
}

void super_free(void*){}

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

узнай — какая проблема. А то если я скажу, опять начнёте матом ругаться.

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

Память в стеке выделяется точно так же, как в перемещающем GC.

а затраты времени на перемещение в перемещающем GC ты конечно не считаешь, да? Он у тебя с помощью магии перемещает? REP MOVS для дебилов, да?

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

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

не понимаю. Объясни. Желательно с примером.

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

Не включает и никогда не включало. Целые числа - это классы эквивалентностей пар натуральных, вещественные числа - классы эквивалентностей фундаментальных последовательностей пар классов эквивалентностей троек натуральных.

у вас на Марсе другая арифметика? Перевод на земной язык будет?

И да, как вы там на Марсе обходитесь без единицы в своих вещественных числах? Соотношение e^{i \pi} + 1 = 0 не работает?

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

Заебись, а когда память закончится, то что делать?

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

Что тебе объяснить? иди и прочитай любой алгоритм сборки.

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

у вас на Марсе другая арифметика?

При чем тут Марс?

Перевод на земной язык будет?

Оно и было на земном, русском языке. Классическое определение целых и вещественных чисел. Обычно это все на первом курсе матфака проходят.

И да, как вы там на Марсе обходитесь без единицы в своих вещественных числах?

Там есть единица. Эта последовательность, эквивалентная 1, 1, 1, ...

Соотношение e^{i \pi} + 1 = 0 не работает?

Это соотношение как раз и задается в вещественных. Точнее - в комплексных. Единица и ноль тут комплексные, а никакие целые.

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

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

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

Теория чисел занимается целыми числами.

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

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

Определения целых/рациональных/вещественных обычно проходят на первой-второй лекции матана. Но ты этих определений не знаешь.

как и основы теории чисел.

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

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

Определения целых/рациональных/вещественных обычно проходят на первой-второй лекции матана.

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

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

Нет.

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

При чем тут перемещение, если речь велась о выделении памяти?

*, а когда память закончится, то что делать?

эти посты писали разные люди, или один идиот?

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

Нахрена вам вообще это красование знанием терминов математики. Лари Уолл, гуманитарий, спроектировал ЯП, Джордж Буш джуниор с ай кью меньше средней домохозяйки стал президентом. А вам что поанонировать на терминологию хочется? Какой толк от ваших матанов, если в жизни другие вещи рулят? Задротство?

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

Какой толк от ваших матанов, если в жизни другие вещи рулят?

Криптография, например.

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

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

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

Это соотношение как раз и задается в вещественных. Точнее - в комплексных. Единица и ноль тут комплексные, а никакие целые.

вот в этом и фишка. На самом деле, int и float — это никакие не вещественные и не целые числа. Это просто модели представления ЧИСЕЛ(вообще) внутри компьютера. Int НЕ эквивалентно целым, а float НЕ эквивалентно вещественным. Мало того, эквивалентного множества нет, и быть не может. Хотя-бы потому, что любое счётное множество бесконечно, и любое множество в компьютере конечно, и стало быть счётным в математическом смысле быть НЕ может.

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

Если тебе интересно продолжить своё образование, то знай: множество int полностью и однозначно преобразуется в множество double, т.к. в большинстве архитектур на сегодня множество int имеет 4294967296 элементов, и в множестве double КАЖДОМУ из этих эл-тов можно найти ОДНОЗНАЧНОЕ отображение. В силу того, что мантисса double является КОНЕЧНЫМ(sic!) множеством из 4503599627370496 эл-тов. Кроме мантиссы есть конечно ещё и 11 бит порядка, но в данном случае он не имеет значения, т.к. его величина однозначно следует из исходного целого числа, и составляет целую часть логарифма по осн. 2 из данного числа(с учётом смещения).

Таким образом, множество int полностью и однозначно отображается в множество double. И потому, преобразование int->double имеет смысл, и правомерно.

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

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

Лари Уолл, гуманитарий, спроектировал ЯП

который никому не нужен, и в сраном говне.

Джордж Буш джуниор с ай кью меньше средней домохозяйки стал президентом.

страны, которая просрала все свои ништяки, и никому не нужна, и в сраном говне.

Какой толк от ваших матанов, если в жизни другие вещи рулят?

просрать то, что тебе досталось бесплатно?

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

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

подтверждает. Миром правят математики. КаГБэ.

Зато подтверждает, что чем математик умней, чем больше шансов закончить в дурдоме.

тебе это не грозит.

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

который никому не нужен, и в сраном говне.

Извини меня, всему свое время, посмотрим как сраный пистон/пых продержит монополию в вебе 10 лет. Уже в начале слили

росрать то, что тебе досталось бесплатно?

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

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

страны, которая просрала все свои ништяки, и никому не нужна, и в сраном говне.

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

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

Извини меня, всему свое время, посмотрим как сраный пистон/пых продержит монополию в вебе 10 лет. Уже в начале слили

ты не с тем споришь. Я разве защищал когда-то пых/пистон? Наоборот, я всегда считал эти ЯП чем-то вроде sed, годных разве на то, что-бы написать какую-то поделку на злобу дня. Если мне заплатят денег за замену в тексте слово xyz на zyx, я напишу sed 's/xyz/zyx/g'. Если мне заплатят денег за какую-то хоумпагу, я возьму php, и сделаю это. Говно.

Люди хотят срать.

Тебе жалко? Принцессы тоже какают, относись к этому философски.

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

Это ты правильно сказал. Но нужны были-бы МЫ? А профессорские детки === глупые тупые дойные коровы, которых надо доить, и на которых надо ездить. Потому-что безмозглая скотина. За-то с жирным мясом.

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

Ага, толстожопый нигер сейчас поперхнулся гамбургером, на который ты ему заработал.

не. Мой толстожопый о таком не думает, и ЛОР не читает. AFAIK он ваще читать не умеет. Думает, что ему все должны. Да и пусть думает, я не против.

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

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

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

Некоторые обиженные на это обижаются, но это не моя проблема. Некоторые неудобства только. Не вижу смысла меняться.

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

Он не думает и не читает. Ему это нахненужно. Он просто занял деньжонок у всего мира и никогда не отдаст.

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

Он не думает и не читает. Ему это нахненужно. Он просто занял деньжонок у всего мира и никогда не отдаст.

не всё так просто — он должен. Мне — отдаёт. Куда денется с подводной лодки? В этом мире делить на ноль умею только я.

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

Ну ладно, лично тебе отдаст, остальных поимеет.

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

А определения дают даже в сельской школе.

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

Нет.

Да. И, еще раз, хватит говорить о том, в чем не разбираешься.

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

Мало того, эквивалентного множества нет, и быть не может.

Почему же? Может. Классы вычетов - вполне себе int. Если подумать, то можно и для флоатов найти модель. Хотя я уверен, что уже подумали, так что надо только погуглить.

Таким образом, все твои отсылки к множествам чисел оставь при себе.

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

Таким образом, множество int полностью и однозначно отображается в множество double.

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

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

типизация в сишечке не слабая

Наличие автоматических кастов типов целых чисел и автоматических кастов типов указателей — это черты слабой типизации.

целое число без потерь преобразуется в вещественное

36028801313931392 не представимо в IEEE754-double без потери точности.

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

не всё так просто — он должен. Мне — отдаёт.

Хоть в рот моча - все божья роса, ага.

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

у него 32-битный int, там такого числа нет.

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

Ах да, и вообще double — это вообще не вещественные числа. Это такое множество целых чисел, которое компьютер обрабатывает так, как будто бы они отображаются на определённые вещественные, а потом обратно.

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

или, если еще более точно - на диапазоны рациональных.

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

Это сложение вещественного и вещественного

Не гони!

int a = 2;
double b = 2.0;
double c = a + b;
Надеюсь, так тебе понятнее, что это сложение целого и вещественного. Здесь используется _неявное_ приведение типов.

Целое — частный случай вещественного

Опять гонишь! Сравни результат с сишечке 1/2 и 1.0/2.0. Если целое - частный случай вещественного, то результат должен быть один и тот же, а это не так.

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

Почему же? Может. Классы вычетов - вполне себе int.

не поле.

Если подумать, то можно и для флоатов найти модель. Хотя я уверен, что уже подумали, так что надо только погуглить

дык и погугли.

Таким образом, все твои отсылки к множествам чисел оставь при себе.

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

вообще-то тут про действия над double+int в языке C, неуч.

Какую структуру сохраняет описанная тобой

без ненормативной лексики ты не можешь? Ты пьян? Иди, проспись.

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

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

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

Наличие автоматических кастов типов целых чисел и автоматических кастов типов указателей — это черты слабой типизации.

и что?

36028801313931392 не представимо в IEEE754-double без потери точности.

я знаю.

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

Ах да, и вообще double — это вообще не вещественные числа.

угу. А int — это НЕ целые числа. Потому-что множество целых чисел бесконечно, а множество int — таки конечно.

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

Надеюсь, так тебе понятнее, что это сложение целого и вещественного. Здесь используется _неявное_ приведение типов.

это СЛОЖЕНИЕ double и double. Данный факт никак не противоречит тому, что ПЕРЕД этим происходит преобразование int --> double.

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

Джит никак не связан со сборщиком мусора.

Как это не связан, если карту корневых ссылок строит именно он?

Не будет.

Почему?

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

тут кричали, что у них GC — «только инкремент». Это довольно грустно, что в их коде — всё работает, а вот в моём — почему-то нет. Может ты мне объяснишь, как их сборщик умудряется выделять память «только инкрементом», причём она не кончается? И как он выделяет регистровую память?

А то мне — ещё грустнее, чем этому ослику...

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

это СЛОЖЕНИЕ double и double.

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

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

Но я человек, я вижу сложение целого и вещественного. Программа пишется для людей, ведь так?

так. Потому я и пишу:

double x;
int y;
double z = x + (double)y;
хотя моему компилятору это и не нужно.

Как пишут разные быдлокодеры — меня не волнует.

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

С нормальным сборщиком мусора память от реконструкции дерева не закончится. А у тебя закончится.

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

не поле.

Не поле. И что дальше?

вообще-то тут про действия над double+int в языке C

еще раз, для особо одаренных - я отвечал на твой пост, где ты говорил про целые и вещественные числа. Об интах и флоатах не было никакого разговора.

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

Как это не связан, если карту корневых ссылок строит именно он?

А кто строит карту корневых ссылок в языке со сборкой, но без джита (интерпретируемых или компилируемых в машкод)?

Почему?

потому что не будет.

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

Может ты мне объяснишь, как их сборщик умудряется выделять память «только инкрементом», причём она не кончается?

Если будет кончаться - запустится сборка и память найдется..

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

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

Какое отношение JIT имеет к GC? У всяких там какамлов с какашкелями JIT-ов нет, а GC есть.

И да, llvm, пара плагинчиков для clang'а и соответствующий рантайм и будет у тебя ЛЮБОЙ GC.

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

Вот только невостребован он в С и даже в С++, там немного другой подход к разработке

Там языки убогие настолько, что задача полного анализа pointer aliasing становится неразрешимой, и от GC будет мало пользы.

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

а затраты времени на перемещение в перемещающем GC ты конечно не считаешь, да? Он у тебя с помощью магии перемещает?

Выигрыш от компактификации многократно перевешивает накладные расходы на перемещение.

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

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

Лол.

Да.

Нет.

И, еще раз, хватит говорить о том, в чем не разбираешься.

У меня для тебя плохие новости. То, что ты умеешь гуглить — не значит, что ты в чем-то разбираешься. Это значит лишь то, что ты умеешь гуглить.

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

С нормальным сборщиком мусора память от реконструкции дерева не закончится. А у тебя закончится.

тогда не говори, что «только инкремент». Пойми — либо крестик, либо трусы. Чудес не бывает в этом мире. Да, у меня рухнет этот код. У тебя — зависнет. Я такое наблюдал неоднократно. Бороться с нехваткой мозгов можно только покупкой новых мозгов. Повторяю — чудес не бывает. Кнут ещё в семидесятых это всё доказал, и у него есть пруфы, со строгим матаном. Ищи ошибку, если такой умный. Я верю Кнуту, а не тебе.

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

Не поле. И что дальше?

Всё. В не поле не определено умножение и деление. Оно не нужно на практике. В вычетах определено лишь сложение. (да и то со многими оговорками)

Доопределение например до поля Галуа приводит к чудовищному удорожанию операций, и тоже не нужно IRL (и только в некоторых особых приложений вроде связи с космическими аппаратами типа Вояджера применяется. Да и там решение берётся тупым перебором, ибо математики так ничего и не придумали лучше).

еще раз, для особо одаренных - я отвечал на твой пост, где ты говорил про целые и вещественные числа. Об интах и флоатах не было никакого разговора.

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

В следующий раз помни, что _я_ пишу исключительно про множества, которые можно *посчитать*. А чего нет, того нельзя считать. Как этих твоих «целых чисел».

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

Может ты мне объяснишь, как их сборщик умудряется выделять память «только инкрементом», причём она не кончается?

Если будет кончаться - запустится сборка и память найдется..

за сигаретами сбегаешь? Пока твой GC всё повесил? Помни, что память *одна* в большинстве случаев, и ВСЁ ждёт, пока эта память занята. Например твоим GC. Намного лучше(дешевле!) повесить пару ядер на вычисление оптимального выделенного блока, чем вешать ВСЁ. Потому сишный malloc(3) предпочтителен в 95% случаев. А если ты не в состоянии сделать free(3) в нужный момент — вон из профессии. Никакая прокладка типа allways jit'а тебя не спасёт от течки. Смирись с этим.

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

Какое отношение JIT имеет к GC?

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

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

GC *всегда* непереносим. Ибо прибит гвоздями к машине(возможно — к виртуальной).

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

это не баг, а фича. Не надо обсираться на каждом шагу, и всё будет хорошо. А если течка у тебя регулярная, то смирись, что ты — баба.

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

Выигрыш от компактификации многократно перевешивает накладные расходы на перемещение.

сиё есть бред и мечта. Доказательство опубликовано Кнутом более 30 лет назад.

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

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

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

Там языки убогие настолько, что задача полного анализа pointer aliasing становится неразрешимой, и от GC будет мало пользы.

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

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

Доказательство опубликовано Кнутом более 30 лет назад.

Я думаю, что тогда были совсем другие сборщики.

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

Я думаю, что тогда были совсем другие сборщики.

математика тогда тоже была совсем другой? Ну тогда извини...

Hint: матан «исправляется» только магией. А делить на ноль умеет только Б-г.

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

алгоритмы НЕ стали «другими». Они только развиваются и улучшаются. Причём почти всегда в сторону специализации. Т.е. старый алгоритм затачивают под новый случай. Но принципиально в них ничего не меняется.

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

а с wm тоже будет не переносим. Точнее, тебе придётся эту твою wm везде таскать для «переносимости». Т.е. это конечно ххорошо, если тебе её по любому надо таскать, как например в javascript, и мирится с её overhead'ом.

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

тогда не говори, что «только инкремент».

Хорошо, не только. Но этим «не только» можно полностью пренебречь. То есть 99.9% времени будет занимать именно инкремент.

Да, у меня рухнет этот код. У тебя — зависнет.

С чего же он зависнет? Ничего подобного.

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

Всё. В не поле не определено умножение и деление.

В кольце определено и сложение и умножение. Кольцо - не поле.

Оно не нужно на практике.

Конечно нужно. Вот твой int - как раз пример полезного кольца.

В вычетах определено лишь сложение. (да и то со многими оговорками)

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

Доопределение например до поля Галуа приводит к чудовищному удорожанию операций

А зачем?

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

На полях Галуа основан матаппарат самокорректирующихся кодов. Без них не будет работать цифровая связь и твои инторнеты.

ОК. В таком случае, ты зря потратил своё время, доказывая мне очевидное.

Чего же ты спорить начал, ебанашка?

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

Пока твой GC всё повесил?

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

Помни, что память *одна* в большинстве случаев, и ВСЁ ждёт, пока эта память занята.

Открой для себя конкурентные инкрементальные сборщики.

Потому сишный malloc(3) предпочтителен в 95% случаев. А если ты не в состоянии сделать free(3) в нужный момент — вон из профессии.

К сожалению, маллок/фри - это медленно, сильно медленно. Зачем делать программу, которая будет работать медленнее в тысячи или даже миллионы раз?

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

Только благодаря ей твой GC имеет нужную информацию о переменных в периметре GC.

Нет, не благодаря ей. Есть куча языков без джита, но с ГЦ.

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

сиё есть бред и мечта.

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

Доказательство опубликовано Кнутом более 30 лет назад.

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

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

Hint: матан «исправляется» только магией.

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

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

Причём почти всегда в сторону специализации.

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

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

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

Хорошо, не только. Но этим «не только» можно полностью пренебречь. То есть 99.9% времени будет занимать именно инкремент.

ага. В синтетических тестах, где для массива в 1000 эл-тов имеется 64Гб RAM. На боевом сервере это всё начинает тупить и тормозить, хотя там тоже 64Гб, но массивов там 100500, и размером они по 100500.

С чего же он зависнет? Ничего подобного.

так и будет, когда твой перемещающий GC начнёт _перемещать_. Включи голову и осознай, что для этого нужно ВСЁ останавливать.

ИЧСХ, если у тебя этот твой GC будет НЕ работать 99.9% времени, то когда он таки включится, работы накопится в тысячу раз БОЛЬШЕ, чем если-бы он работал на каждой аллокации. Но ты же 999 аллокаций делал только инкремент. А теперь — страдай и жди.

Повторяю: чудес не бывает, если ты отложил работу, то ты НЕ СДЕЛАЛ работу. Так вот, GC именно ОТКЛАДЫВАЕТ работу по наведению порядка.

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

В кольце определено и сложение и умножение. Кольцо - не поле.

может ты самостоятельно освежишь свои знания?

Сложение определено безо всяких оговорок.

6часов + 6часов == сколько часов?

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

3часа*4часа == сколько часов? А сколько 6часов*6часов?

Доопределение например до поля Галуа приводит к чудовищному удорожанию операций

А зачем?

затем, что оно(умножение/деление) _неоднозначное_. Даже если делитель не равен нулю. Т.е. если в целых/вещественных «делить на ноль нельзя», то в вычетах делить ВООБЩЕ нельзя, кроме некоторых специальных случаев (например можно умножать и делить на 1).

Доопределение до поля Галуа снимает проблему неоднозначности, но возникает проблема дебиловрядовых программистов, которые стройными рядами уходят в лечебницы для психов. Ибо понять 2*2==1 они почему-то не могут.

На полях Галуа основан матаппарат самокорректирующихся кодов. Без них не будет работать цифровая связь и твои инторнеты.

я в курсе. А работать будет, просто медленнее.

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

В случае малого дерева сборка будет быстрее, чем вызов одного маллока.

докажи это странное заключение.

Открой для себя конкурентные инкрементальные сборщики.

они освобождают какую-то другую память?

К сожалению, маллок/фри - это медленно, сильно медленно.

это пока сборка не запустилась, а откладывается. Да, тогда malloc медленный. Вот только работа GC всё равно только ОТКЛАДЫВАЕТСЯ.

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

Нет, не благодаря ей. Есть куча языков без джита, но с ГЦ.

ага: bash, php...

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

может ты самостоятельно освежишь свои знания?

Ага, замечательно. Быстро мне определение кольца - только без подсказок из гугла!

6часов + 6часов == сколько часов?

Я не знаю, какая мат. структура у тебя на часах. может Z_12, может Z_24, может N, может что еще изощреннее. Я мысли читать не умею.

затем, что оно(умножение/деление) _неоднозначное_.

Ну ради бога. Все равно все пользуются интами и довольны. Умножение и деление кстати вполне однозначны, только деление не всюду определено (только если делитель с модулем взаимно просты).

то в вычетах делить ВООБЩЕ нельзя, кроме некоторых специальных случаев (например можно умножать и делить на 1).

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

я в курсе. А работать будет, просто медленнее.

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

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

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

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

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

область применимости описана — когда памяти не хватает, и приходится запускать GC (или когда maloc(3) уже не справляется, и тратит слишком много времени на поиск)

А когда памяти как грязи — мой super_malloc работает ничуть не хуже, и не медленнее. Особенно в 64х битах и со свопом (куда и будет складываться автоматически ненужный мусор)

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

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

а те теоремы тоже устарели? Сумма квадратов катетов уже не равна квадрату гипотенузы? Да? Ну дай пруф на ютуб, я посмотрю ролик с доказательством, и пойду топится.

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

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

это верно. Осталось немного: докажи, что стратегия использования памяти в ФП сама по себе является оптимальной для существующих архитектур. А то для меня это не очевидно.

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

докажи это странное заключение.

А чего тут доказывать? Вся сборка состоит из обхода корней и перемещения достижимых данных. Допустим, у тебя десяток корней (преувеличим) и пара десятков элементов в дереве - значит, на все про все ты затратишь меньше сотни разыменовываний и те самые два десятка memcpy. По сравнению с тормозным маллоком - это совсем не много.

они освобождают какую-то другую память?

Нет, ту же самую. но при этом выполнение программы им останавливать не надо.

это пока сборка не запустилась, а откладывается. Да, тогда malloc медленный. Вот только работа GC всё равно только ОТКЛАДЫВАЕТСЯ.

Смотри, фишка в том, что _удаление_ информации с перемещающим сборщиком вообще не вызывает времени. Выделение - вызывает очень мало времени. Реальное время занимает компактификация - которая зависит от размера _достижимых_ данных. Другими словами, с ростом интенсивности выделения/освобождений памяти стоимость GC практически не растет. С другой стороны она растет с ростом текущей потребности памяти.

С аллокаторами все наоборот - их стоимость практически не растет с ростом потребностей в памяти, но линейна по вызываемым маллок/фри.

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

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

Повторяю: чудес не бывает, если ты отложил работу, то ты НЕ СДЕЛАЛ работу. Так вот, GC именно ОТКЛАДЫВАЕТ работу по наведению порядка.

Да нет, GC совершает ДРУГУЮ работу. Это другой алгоритм. И сложность у GC и у аллокаторов разная (зависит от разных параметров).

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

так и будет, когда твой перемещающий GC начнёт _перемещать_. Включи голову и осознай, что для этого нужно ВСЁ останавливать.

Еще раз - читай про конкурентные сборщики.

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

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

Тебе вопрос на засыпку - сколько будет время занимать сборка перемещающего сборщика после выполнения задачи? Правильно - 0 (точнее время, слабо отличимое от нуля, сколько-то он работать все-таки будет). Сам догадаешься почему, или тебе объяснить?

область применимости описана — когда памяти не хватает, и приходится запускать GC (или когда maloc(3) уже не справляется, и тратит слишком много времени на поиск)

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

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

а те теоремы тоже устарели?

Теоремы не устарели. Я говорил о методах доказательства.

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

это верно. Осталось немного: докажи, что стратегия использования памяти в ФП сама по себе является оптимальной для существующих архитектур. А то для меня это не очевидно.

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

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

Ага, замечательно. Быстро мне определение кольца - только без подсказок из гугла!

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

Я не знаю, какая мат. структура у тебя на часах. может Z_12, может Z_24, может N, может что еще изощреннее. Я мысли читать не умею.

ты часов не видел? 12 цифр. И да, с 24ю только хуже, ибо неоднозначностей только больше. Т.ч. считай как попроще, с 12.

Ну ради бога. Все равно все пользуются интами и довольны. Умножение и деление кстати вполне однозначны, только деление не всюду определено (только если делитель с модулем взаимно просты).

да потому-что int'ы это НЕ вычеты. Твоя изначальная предпосылка ложна. Они «вычеты» исключительно по сложению, а по умножению/делению — это конечная подобласть таки области целых. Т.е. результат умножения/деления int эквивалентен умножению/делению целых, если нет переполнения. А если есть — UB для сишечки.

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

ты ошибаешься. Всё намного хуже, если модуль — не целая степень простого числа. Проблема в том, что по модулю 12, 2*6==6*6==3*4==...==0; И ты не можешь разделить даже ноль на что угодно.

А если модуль — целая степень простого числа, то всё только хуже. Вот тебе таблица умножения по модулю 3

0*2=0
1*2=2
2*2=1
Таблица умножения по модулю 7 имеет намного более смешной вид, попробуй её составь, раз ты такой умный. Да, можешь погуглить, я только за. Ибо уверен, что ты в этом нихрена не понимаешь. И проверять это не имеет смысла.

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

А чего тут доказывать? Вся сборка состоит из обхода корней и перемещения достижимых данных. Допустим, у тебя десяток корней (преувеличим) и пара десятков элементов в дереве - значит, на все про все ты затратишь меньше сотни разыменовываний и те самые два десятка memcpy. По сравнению с тормозным маллоком - это совсем не много.

ОК, а что такого тормозного нужно сделать моему malloc'у? Выиграть партию в преферанс?

Нет, ту же самую. но при этом выполнение программы им останавливать не надо.

это как, если у тебя скажем массив, с которым ты СЕЙЧАС работаешь наполовину в одном месте, а на другую половину — в другом?

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

Смотри, фишка в том, что _удаление_ информации с перемещающим сборщиком вообще не вызывает времени. Выделение - вызывает очень мало времени. Реальное время занимает компактификация - которая зависит от размера _достижимых_ данных. Другими словами, с ростом интенсивности выделения/освобождений памяти стоимость GC практически не растет. С другой стороны она растет с ростом текущей потребности памяти.

тебе просто не подходит ЭТОТ malloc(3). Используй другой, не вижу проблемы.

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

и избавить меня от повторения очевидных вещей.

Но ты же этих вещей не знаешь. Или не помнишь. Значит - надо повторить. А ну быстро в гугл иди!

ты часов не видел? 12 цифр. И да, с 24ю только хуже, ибо неоднозначностей только больше. Т.ч. считай как попроще, с 12.

Замечательно, 6+6=0. Дальше что?

да потому-что int'ы это НЕ вычеты.

Нет, это именно что вычеты.

Они «вычеты» исключительно по сложению, а по умножению/делению — это конечная подобласть таки области целых.

По умножению они тоже точно такие же вычеты, т.к. умножение нельзя определить иначе, не нарушив дистрибутивность, то есть тогда у тебя в интах будет ситуация, при которой a+a!=2a. Ну а операции деления, как противоположной умножению на интах просто не определено, есть только целочисленное деление с вариациями.

Т.е. результат умножения/деления int эквивалентен умножению/делению целых, если нет переполнения. А если есть — UB для сишечки.

Хохо, так ты не только начальной алгебры, но и сишки не знаешь? ub - только в случае знаковых, а вот беззнаковые как раз обязаны modulo 2^n - то есть вести себя как классы вычетов при сложении и умножении.

ты ошибаешься. Всё намного хуже, если модуль — не целая степень простого числа.

Это ты сам хуйню придумал.

Проблема в том, что по модулю 12, 2*6==6*6==3*4==...==0; И ты не можешь разделить даже ноль на что угодно.

Деление - это, по определению, умножение на обратный элемент, а не то, что ты придумал. 0/5 = 0*5^-1, например, то есть ноль, по определению нуля. У пятерки в Z_12 обратный есть (как и у любого числа взаимно простого с 12), по-этому все что угодно в этом кольце можно делить на пятерку.

Таблица умножения по модулю 7

Кольцо классов вычетов по модулю 7 является полем, да будет тебе известно (поле Галуа GF(7)). В нем можно умножать что угодно на что угодно и делить что угодно на что угодно (кроме нуля, конечно).

ну, например, в этом поле 5*6=2, 3*4=5, 6*4=3. Таблицу целиком мне лениво писать.

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

тебе просто не подходит ЭТОТ malloc(3). Используй другой, не вижу проблемы.

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

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

ОК, а что такого тормозного нужно сделать моему malloc'у?

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

это как

Иди и гугли, как. Что гуглить я тебе указал, конкретные алгоритмы найдешь сам.

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

Иди и гугли, как. Что гуглить я тебе указал, конкретные алгоритмы найдешь сам.

Есть мнение, что ты сам эти алгоритмы не знаешь. Ибо не смотря на название, они не делают то, что говоришь ты. И еще, современные GC плохо работают тогда, когда мало мусора и много объектов, которые реально нужны. Особенно это все проявляется, когда речь идет хотя бы о нескольких десятках гигобайт. В то время как кастомные аллокаторы на C++ показывают себя очень хорошо. Поэтому, повторюсь, не существует оптимальных алгоритмов на все случаи жизни. Опциональный(полностью) сборщик в C++ может быть полезен, возможно, что он таки появится рано или поздно в стандарте.

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

Тебе вопрос на засыпку - сколько будет время занимать сборка перемещающего сборщика после выполнения задачи? Правильно - 0 (точнее время, слабо отличимое от нуля, сколько-то он работать все-таки будет). Сам догадаешься почему, или тебе объяснить?

нет, спасибо. Но меня никто не просит писать helloworld'ы, задача которых — напечатать helloworld и завершиться.

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

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

Теоремы не устарели. Я говорил о методах доказательства.

а я говорил о _доказанных_ теоремах.

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

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

именно по этому аллокатор и НЕ ВХОДИТ в спецификацию C/C++. Мало того, в эту спецификацю входит возможность его ЗАМЕНИТЬ. Т.е. использовать свой malloc, или перезагрузить class::new, или даже ::new. Так, как нужно в _этой_ задаче.

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

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

Но ты же этих вещей не знаешь. Или не помнишь. Значит - надо повторить. А ну быстро в гугл иди!

я оттуда не выходил. Это ты мне почему-то запрещаешь его юзать. А я — наоборот, и сам юзаю, и тебе советую. Ибо незнание != невежество. Невежество, это когда у тебя есть гугл, но ты НЕ ХОЧЕШЬ им пользоваться.

Замечательно, 6+6=0. Дальше что?

дальше то, что 0+0==1+11==2+10==...==0. Потому, что есть «ноль» — неоднозначно. Сравни с натуральными числами, в которых 0+0==0, ВСЕГДА. Из неоднозначности сложения следует неоднозначность всего остального, и до кучи — невозможность ВСЕХ обратных операций. Для обычных чисел есть только проблема с неоднозначностью умножения на ноль, из которой следует невозможность деления на ноль.

(с отрицательными числами тоже есть проблемы, но они исправимы. Например неоднозначно деление с остатком. Это не проблема, т.к. математики постулируют, что истинный остаток всегда >=0. О чём, кстати, не знают большинство архитектур, вроде x86/amd64. Однако с вычетом проблемы не устранимы, как и при делении на ноль)

Нет, это именно что вычеты.

тогда определи умножение вычетов. И сравни с тем, что есть.

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

ВНЕЗАПНО: в поле Галуа — можно. Вот только это ДРУГОЕ «умножение», которое например для модуля 3 даёт 2*2=1. А теперь попробуй определить «умножение» например по модулю 16, и удивись. Как не странно, дистрибутивность там работает, как и деление(исключая /0 конечно).

Ну а операции деления, как противоположной умножению на интах просто не определено, есть только целочисленное деление с вариациями.

потому-что int-ы != вычеты. А подмножество целых чисел. Ограниченное и конечное. Т.е. это такие целые, из которых вычеркнуто всё, больше INT_MAX и меньше -(INT_MAX+1). И если аргумент и/или результат выходит за диапазон, то «результат» === тоже самое UB, как и при делении на ноль. Это так в сишечке. В других ЯП обычно просто бардак, на который всем пофиг.

Хохо, так ты не только начальной алгебры, но и сишки не знаешь? ub - только в случае знаковых, а вот беззнаковые как раз обязаны modulo 2^n - то есть вести себя как классы вычетов при сложении и умножении.

пруф найди пожалуйста. Я не осилил.

ты ошибаешься. Всё намного хуже, если модуль — не целая степень простого числа.

Это ты сам * придумал.

Это тебе к Галуа с такими вопросами — он придумал. Мопед не мой.

Деление - это, по определению, умножение на обратный элемент, а не то, что ты придумал.

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

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

Кольцо классов вычетов по модулю 7 является полем, да будет тебе известно (поле Галуа GF(7)). В нем можно умножать что угодно на что угодно и делить что угодно на что угодно (кроме нуля, конечно).

ну, например, в этом поле 5*6=2, 3*4=5, 6*4=3. Таблицу целиком мне лениво писать.

а погуглить тебе тоже лениво? Вот тебе таблица умножения по модулю 256

i alpha index i alpha index i alpha index i alpha index i alpha index i alpha ind
000 001  -1   043 119 218   086 177 219   129 023 112   172 123 220   215 239 170
001 002   0   044 238 240   087 127 189   130 046 192   173 246 252   216 195 251
002 004   1   045 193  18   088 254 241   131 092 247   174 241 190   217 155  96
003 008  25   046 159 130   089 225 210   132 184 140   175 255  97   218 043 134
004 016   2   047 035  69   090 223  19   133 109 128   176 227 242   219 086 177
005 032  50   048 070  29   091 163  92   134 218  99   177 219  86   220 172 187
006 064  26   049 140 181   092 091 131   135 169  13   178 171 211   221 069 204
007 128 198   050 005 194   093 182  56   136 079 103   179 075 171   222 138  62
008 029   3   051 010 125   094 113  70   137 158  74   180 150  20   223 009  90
009 058 223   052 020 106   095 226  64   138 033 222   181 049  42   224 018 203
010 116  51   053 040  39   096 217  30   139 066 237   182 098  93   225 036  89
011 232 238   054 080 249   097 175  66   140 132  49   183 196 158   226 072  95
012 205  27   055 160 185   098 067 182   141 021 197   184 149 132   227 144 176
013 135 104   056 093 201   099 134 163   142 042 254   185 055  60   228 061 156
014 019 199   057 186 154   100 017 195   143 084  24   186 110  57   229 122 169
015 038  75   058 105   9   101 034  72   144 168 227   187 220  83   230 244 160
016 076   4   059 210 120   102 068 126   145 077 165   188 165  71   231 245  81
017 152 100   060 185  77   103 136 110   146 154 153   189 087 109   232 247  11
018 045 224   061 111 228   104 013 107   147 041 119   190 174  65   233 243 245
019 090  14   062 222 114   105 026  58   148 082  38   191 065 162   234 251  22
020 180  52   063 161 166   106 052  40   149 164 184   192 130  31   235 235 235
021 117 141   064 095   6   107 104  84   150 085 180   193 025  45   236 203 122
022 234 239   065 190 191   108 208 250   151 170 124   194 050  67   237 139 117
023 201 129   066 097 139   109 189 133   152 073  17   195 100 216   238 011  44
024 143  28   067 194  98   110 103 186   153 146  68   196 200 183   239 022 215
025 003 193   068 153 102   111 206  61   154 057 146   197 141 123   240 044  79
026 006 105   069 047 221   112 129 202   155 114 217   198 007 164   241 088 174
027 012 248   070 094  48   113 031  94   156 228  35   199 014 118   242 176 213
028 024 200   071 188 253   114 062 155   157 213  32   200 028 196   243 125 233
029 048   8   072 101 226   115 124 159   158 183 137   201 056  23   244 250 230
030 096  76   073 202 152   116 248  10   159 115  46   202 112  73   245 233 231
031 192 113   074 137  37   117 237  21   160 230  55   203 224 236   246 207 173
032 157   5   075 015 179   118 199 121   161 209  63   204 221 127   247 131 232
033 039 138   076 030  16   119 147  43   162 191 209   205 167  12   248 027 116
034 078 101   077 060 145   120 059  78   163 099  91   206 083 111   249 054 214
035 156  47   078 120  34   121 118 212   164 198 149   207 166 246   250 108 244
036 037 225   079 240 136   122 236 229   165 145 188   208 081 108   251 216 234
037 074  36   080 253  54   123 197 172   166 063 207   209 162 161   252 173 168
038 148  15   081 231 208   124 151 115   167 126 205   210 089  59   253 071  80
039 053  33   082 211 148   125 051 243   168 252 144   211 178  82   254 142  88
040 106  53   083 187 206   126 102 167   169 229 135   212 121  41   255 000 175
041 212 147   084 107 143   127 204  87   170 215 151   213 242 157
042 181 142   085 214 150   128 133   7   171 179 178   214 249  85
Листинг 13. Lock-up-таблица для GF(256) Первая слева колонка - полиномы/индексы (обычно обозначается как i), вторая - таблица степеней примитивного полинома 2 (обычно обозначается как alpha_of), третья - индексы, соответствующие данному полиному (обычно обозначается как index_of).

http://www.insidepro.com/kk/027/027r.shtml

а теперь объясни, ГДЕ ты видел ТАКОЕ умножение? В котором 2**8==29

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

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

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

Регистровые переменные в пул не вернуть? Не используй регистровые переменные. Не используй стек. Да, на сишечке с интами и глупыми указателями не очень удобно(оператор = и всякие +- не перезагрузить, и придётся делать функции), используй C++.

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

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

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

это как, если у тебя скажем массив, с которым ты СЕЙЧАС работаешь наполовину в одном месте, а на другую половину — в другом?

Иди и гугли, как. Что гуглить я тебе указал, конкретные алгоритмы найдешь сам.

я их без тебя и твоего гугла знаю — всё затормозить, и начать двигать туда-суда. Что в php, что в javascript'е, который в FF/Opera/IE. Потому-то это дерьмо и тормозит, и жрёт память сотнями и тысячами метров. Об этом любой школьник знает. Про вашу ынтерпрайзную java я тоже в курсе, которой нужен отдельный сервер под какой-то сраный сайт на 1К юзеров.

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

Опциональный(полностью) сборщик в C++ может быть полезен, возможно, что он таки появится рано или поздно в стандарте.

будь мужиком, сделай СЕЙЧАС. У тебя есть для этого все возможности. Я уже делал, там нет ничего такого уж сложного.

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

При поддержке компилятора будет лучше. Можно сделать как плагинчик к clang'у.

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

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

9000мб в стандартной ФП-программе выделяется и освобождается за время порядка секунд, постоянно.

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

я их без тебя и твоего гугла знаю — всё затормозить

Нет. я же сказал - гугли. Алсо, в том же эрланге, например, сборщик в каждом процессе свой, независимый. СБорка во дном процессе не останавливает другие и кроме того проходит очень быстро за счет того, что памяти процесс потребляет мало и unidirectional heap.

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

а погуглить тебе тоже лениво?

Зачем мне это гуглить?

Вот тебе таблица умножения по модулю 256

Это не таблица умножения по Z_256. Это поле Галуа GF(2^8). Это разные вещи. В частности, Z_256 не поле.

а теперь объясни, ГДЕ ты видел ТАКОЕ умножение? В котором 2**8==29

Так ты не умножение в поле Галуа смотри а в кольце классов вычетов.

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

Невежество, это когда у тебя есть гугл, но ты НЕ ХОЧЕШЬ им пользоваться.

так воспользуйся. Не будь невеждей.

дальше то, что 0+0==1+11==2+10==...==0.

Ну да. Прямо как в интах.

Сравни с натуральными числами, в которых 0+0==0, ВСЕГДА.

Ну и тут 0+0=0 ВСЕГДА.

Из неоднозначности сложения следует неоднозначность всего остального

Я не понимаю откуда ты высрал неоднозначность сложения. Оно вполне однозначно. в Z_12 6+6 = 0. Не 1, не 2, только 0.

и до кучи — невозможность ВСЕХ обратных операций.

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

потому-что int-ы != вычеты.

Тебе тогда нетрудно будет привести пример, где инты - это не вычеты.

Т.е. это такие целые, из которых вычеркнуто всё, больше INT_MAX и меньше -(INT_MAX+1).

Вообще-то речь шла об unsigned, не надо подменять понятия.

пруф найди пожалуйста. Я не осилил.

http://lmgtfy.com/?q=c unsigned integer overflow

Это тебе к Галуа с такими вопросами — он придумал.

Галуа был одним из гениальнейших математиков за всю историю человечества (скорее всего даже - самым гениальным). Не надо приписывать ему придуманную тобой хуйню.

Это ты фантазируешь, что обратный эл-т у тебя один.

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

Если множество конечно, то вопрос единственности открыт.

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

тогда определи умножение вычетов. И сравни с тем, что есть.

Умножение вычетов не надо определять - за меня это уже давным-давно сделали математики. Работает оно так - в кольце классов вычетов Z_n чтобы перемножить два числа надо перемножить их как натуральные, а потом взять остаток от деления на n. И это в точности то, как ведут себя инты.

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

И еще, современные GC плохо работают тогда, когда мало мусора и много объектов, которые реально нужны.

Да, я об этом говорил. Дело все в том что в ФП языках ситуация обратная - обычно мусора сильно больше, чем достижимых объектов.

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

Да нет, как раз то.

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

Регистровые переменные в пул не вернуть?

Опять ты эту хуйню несешь? Какой пул? что и куда ты собрался возвращать, дубина?

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

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

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

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

не нужно IRL

то есть AES IRL не используется, я правильно тебя понял?

В не поле не определено умножение и деление

умножение всюду определено в любом кольце. деление определено на обратимых элементах кольца (единицах)

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

Так ты не умножение в поле Галуа смотри а в кольце классов вычетов.

так дай мне ссылку на такое умножение. А то я не нашёл.

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

Ну и тут 0+0=0 ВСЕГДА.

это потому, что 2**n — допустимый модуль для построения поля Галуа. Но ведь ты его строить отказался. Ты как-то в кольце вычетов умножаешь. Вот и расскажи — КАК.

Я не понимаю откуда ты высрал неоднозначность сложения. Оно вполне однозначно. в Z_12 6+6 = 0. Не 1, не 2, только 0.

проблема в том, что есть разные разложения числа 12. 3*4 или 2*6 например. Потому, когда мы прыгаем на 12 ед. вперёд, невозможно узнать, КАК мы прыгали. Может 3 раза по 4, а может 2 раза по 6. Это и называется — неоднозначность.

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

ага, а значит для элементов 0,1,2,3,4,6 для Z_12 соорудить обратный эл-т невозможно. Подумаешь — половину множество похерили...

Тебе тогда нетрудно будет привести пример, где инты - это не вычеты.

легко: в int'ах определено умножение и деление, а в вычетах — увы.

Вообще-то речь шла об unsigned, не надо подменять понятия.

да вообще-то без разницы. Пусть будет от 0 до 2*INT_MAX-1.

Умножение вычетов не надо определять - за меня это уже давным-давно сделали математики. Работает оно так - в кольце классов вычетов Z_n чтобы перемножить два числа надо перемножить их как натуральные, а потом взять остаток от деления на n. И это в точности то, как ведут себя инты.

ага. Для Z_12 получаем кучу делителей нуля, ибо 3*4==0, 2*6==0, 6*6==0, и так далее.

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

Ну и тут 0+0=0 ВСЕГДА.

надоело спорить. В вычетах Z_12:

1*2=2;
7*2=2;
2/2=?
Если этого не понимаешь, то извини. Мне больше нечего сказать.

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

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

посмотри в удалённых, я про этот «сюрприз» уже писал. Не ты один тут такой умный.

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

то есть AES IRL не используется, я правильно тебя понял?

нет, неправильно.

умножение всюду определено в любом кольце. деление определено на обратимых элементах кольца (единицах)

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

В поле Галуа умножение тоже частично определено, но ПО ДРУГОМУ.

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

Вот и расскажи — КАК.

Точно так же, как в подполе констант поля Галуа, представь себе. Z_n как поле изоморфна подполю констант GF(n^k),

Потому, когда мы прыгаем на 12 ед. вперёд, невозможно узнать, КАК мы прыгали.

А зачем нам это знать? При чем тут умножение?

Это и называется — неоднозначность.

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

ага, а значит для элементов 0,1,2,3,4,6 для Z_12 соорудить обратный эл-т невозможно.

Для нуля нигде невозможно (потому как на 0 - не делят). Для единицы в любом кольце возможно - обратный единице сама единица и только она. 2,3,4,6 в Z_12 пролетают, да.

легко: в int'ах определено умножение и деление, а в вычетах — увы.

И в вычетах определено, точно так же.

да вообще-то без разницы.

Да вообще-то есть разница. Для знаковых overflow - undefined behaviour, а вот для беззнаковых - должен быть взят остаток по модулю. Что и делает unsigned int изоморфным кольцу классов вычетов.

ага. Для Z_12 получаем кучу делителей нуля, ибо 3*4==0, 2*6==0, 6*6==0, и так далее.

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

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

посмотри в удалённых, я про этот «сюрприз» уже писал. Не ты один тут такой умный.

посмотрел, не писал.

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

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

Вот и изучи. По _определению_ кольца (даже полукольца) умножение любых двух элементов этого кольца _определено_

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

На 2 в z_12 делить нельзя. от этого умножение не становится неоднозначным. Неоднозначно взятие обратного элементе. Не умножение. В int взятие обратного элемента точно так же неоднозначно - ты не можешь однозначно делить int'ы на степени двойки, точно так же есть делители нуля.

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

В поле Галуа умножение тоже частично определено, но ПО ДРУГОМУ.

Любое поле является кольцом, в кольце умножение полностью и однозначно определено, поэтому определено и в любом поле, в том числе - в поле Галуа. Но в поле Галуа еще однозначно определено и деление чего угодно на что угодно (кроме нуля).

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

http://ru.wikipedia.org/wiki/Кольцо_вычетов#.D0.9A.D0.BB.D0.B0.D1.81.D1.81.D1...

википедики слабо знают математику. Попробуй таки составить эту таблицу умножения, и ей воспользоваться. И ты всё поймёшь. Действительно, для поля Галуа можно определить умножение, вот только оно совсем ДРУГОЕ. Цифры другие в таблице. А для вычетов данное правило НЕ работает, т.к. умножение НЕ ОДНОЗНАЧНО.

Т.е. данная математика википедиков бесполезна и не нужна. Это тоже самое, что сказать, что 0/0==17. Можно. А зачем?

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

википедики слабо знают математику.

Ок. Алгебра, Ленг, страница 78.

Попробуй таки составить эту таблицу умножения, и ей воспользоваться.

Составил, воспользовался, какие проблемы?

А для вычетов данное правило НЕ работает, т.к. умножение НЕ ОДНОЗНАЧНО.

Приведи мне пример неоднозначности умножения на вычетах. То есть два таких вычета, результат умножения которых неоднозначен.

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

Т.е. данная математика википедиков бесполезна и не нужна.

Кольца классов вычетов - это в точности все факторкольца натуральных. Они очень нужны.

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

натуральных.

Целых, конечно.

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

А зачем нам это знать? При чем тут умножение?

при том, что умножение — многократный сдвиг числа. Любое число в поле можно разложить на произведение простых чисел, и оно единственно и однозначно. Потому умножением можно пользоваться. А твоим «умножением» пользоваться нельзя, ибо его результат непредсказуем.

Неоднозначность - это если я «а» умножил на «б» и получил то ли «с», то ли «х», то ли х пойми что.

так и есть.

т.е. 2 умноженное на 1/2 получается то-ли 2, то-ли 7. По модулю 12. Но это ещё пол беды, беда в том, что у тебя сам модуль получается неоднозначным способом. Потому-то х..ня и получается, потому-что 2*2*3 можно представить несколькими разными способами. Как именно — хрен его знает. На этом и «держится» твоя математика.

И в вычетах определено, точно так же.

это в каких таких «целых» 2*2==1???

Да вообще-то есть разница. Для знаковых overflow - undefined behaviour, а вот для беззнаковых - должен быть взят остаток по модулю. Что и делает unsigned int изоморфным кольцу классов вычетов.

толку с этой изоморфности, если в кольце всё равно умножение не работает?

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

1. умножение без деления никому не нужно.

2. деление в int таки определено. Что-бы ты там не говорил.

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

да? Ну короче говоря я в курсе про GC без JIT, успокойся.

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

Вот и изучи. По _определению_ кольца (даже полукольца) умножение любых двух элементов этого кольца _определено_

ты пропустил слово «однозначно». Без него твоё «определение» не годно даже для того, что-бы им подтереться. Однозначно.

Ибо в противном случае верно, что 0/0==146%.

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

при том, что умножение — многократный сдвиг числа.

Это ты сам уже придумываешь.

А твоим «умножением» пользоваться нельзя, ибо его результат непредсказуем.

У меня все предсказуемо. Все математики пользуются - и у них тоже все предсказуемо. Может, дело не в умножении?

так и есть.

Нет, в кольце так не есть.

т.е. 2 умноженное на 1/2 получается то-ли 2, то-ли 7.

В Z_12 нету 1/2. Как ты собрался умножать на то, чего нет?

толку с этой изоморфности, если в кольце всё равно умножение не работает?

Во-первых умножение в кольце прекрасно работает. Во-вторых - умножение в кольце вычетов в точности совпадает с умножением в unsigned int. Так что оно или и там и там работает или и там и там не работает. Потому что это одно и то же умножение.

1. умножение без деления никому не нужно.

Нужно, представь себе.

2. деление в int таки определено. Что-бы ты там не говорил.

В int определено деление нацело. Деление, как операция обратная умножению - не определена, т.к. нету элементов обратных четным числам.

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

ты пропустил слово «однозначно».

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

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

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

На 2 в z_12 делить нельзя.

ага. А ещё на 0, на 1, на 3, на 4, и на 6. Классно!

Неоднозначно взятие обратного элементе. Не умножение.

само умножение неоднозначно. Т.е. умножать надо так, что-бы НЕ получилось {0,1,2,3,4,6,8,9,10}. И никак иначе!

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

нет. В int ты можешь выполнять операции с точностью до модуля. Т.е. это и не кольцо вычетов, и не поле Галуа(в поле Галуа GF(q^m)ты можешь умножать с точностью до q^n, где n — любое целое число)

Множество unsigned эквивалентно полю натуральных чисел, из которого вычеркнули все числа большие MAX_INT*2. Потому умножение там определено лишь для результатов И аргументов, которые внутри этого огрызка поля. Как и деление.

За пределами огрызка операции не определены.

А вычеты тут вообще не при чём. В вычетах не определено однозначно умножение, потому они не нужны в качестве int'ов.

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

В поле Галуа умножение тоже частично определено, но ПО ДРУГОМУ.

Любое поле является кольцом, в кольце умножение полностью и однозначно определено, поэтому определено и в любом поле, в том числе - в поле Галуа.

ты забыл, что у нас нет полей. Есть частный случай НЕ поля. Поле, которое с нулём. Для поля Галуа это тоже так. В нём однозначное умножение тоже частично определено, исключая 0. Для нуля однозначное умножение не определено.

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

само умножение неоднозначно.

Да где неоднозначно-то? Можешь привести хоть один пример?

Т.е. умножать надо так, что-бы НЕ получилось {0,1,2,3,4,6,8,9,10}. И никак иначе!

Да нет, почему? Пусть получается.

нет. В int ты можешь выполнять операции с точностью до модуля.

в unsigned int при переполнении берется остаток по модулю. и это ТОЧНО ТАК как ведут себя вычеты. приведи пример, где умножение unsigned int даст не тот же результат, что умножение в Z_(2^32)

Потому умножение там определено лишь для результатов И аргументов, которые внутри этого огрызка поля.

Да нет. Оно определено для всех элементов поля. Если происходит переполнение - берется остаток.

А вычеты тут вообще не при чём. В вычетах не определено однозначно умножение

Пример, пример. один пример - где умножение не определено (не деление, а умножение - то есть пример таких a и b что a*b = c1 и при этом a*b = c2), и второй - где инты ведут себя не так, как вычеты.

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

ы забыл, что у нас нет полей. Есть частный случай НЕ поля. Поле, которое с нулём. Для поля Галуа это тоже так. В нём однозначное умножение тоже частично определено, исключая 0.

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

Для нуля однозначное умножение не определено.

С чего вдруг? Если что-то умножить на ноль - это всегда ноль. Вполне однозначно. Сможешь опровергнуть контр-примером?

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

Ок. Алгебра, Ленг, страница 78.

нету под рукой.

Составил, воспользовался, какие проблемы?

проблема в том, что команда mul твоего CPU использует ДРУГУЮ таблицу умножения. В которой 2**8 получается таки 0 по модулю 256, а вовсе НЕ 29, как в поле Галуа. Причём это касается ВСЕХ чисел, за исключением степеней двойки меньше модуля.

Твоя проблема в том, что количество информации при умножении двух чисел УДВАИВАЕТСЯ, т.е. результат умножения двух чисел занимает вдвое больше бит. Потому обычное умножение НЕВОЗМОЖНО для чисел с фиксированной разрядностью(для любых таких чисел).

Однако, энтропия увеличивается не вдвое, а только на 1 бит. Потому-то можно переставить и поменять биты так, что-бы разрядность «умножения» не изменилась(не всегда. Для Z_12 нельзя). Вот только это будет совсем *другое* «умножение». Которое не имеет никакого отношения к вычетам.

Грубо говоря, при умножении двух отрезков x,y мы получаем отрезок равный x*y, в котором тем не менее полно дыр, которые никогда не получаются(например нет числа 11 среди всех произведений чисел от 0 до 9). И достаточно взять какую-то часть размера x+y, что-бы эти дырки убрать. Проблема только в том, что просто любой(или первый попавшийся, как вика рекомендует) отрезок НЕ подходит. Ибо дырки равномерно разбросаны по всему множеству x*y, а вовсе не гнездятся в его конце.

Приведи мне пример неоднозначности умножения на вычетах. То есть два таких вычета, результат умножения которых неоднозначен.

там другая проблема: Произведения двух вычетов ложатся только НА НЕКОТОРЫЕ точки. Т.е. у тебя на одно произведение приходится сразу несколько комбинаций вычетов. Точно также, как при умножении на ноль. При умножении на ноль ВСЕ точки обращаются в ноль. При умножении на многие вычеты МНОГИЕ РАЗНЫЕ числа дают ОДИН результат.

Т.е. неоднозначность тут как с единицами — 1*1*1*1*... И мы не знаем, СКОЛЬКО было единиц. Но единица — одна. А в вычетах таких «единиц» — МНОГО РАЗНЫХ. Потому с обычными числами неоднозначности и не возникает, т.к. нет разницы, сколько ЕДИНИЦ, ведь 1*1==1. Откуда 1==1*1*... И никак иначе. А вот с вычетами — беда. По твоим правилам получается только несколько произведений из всего множества, в которые и обращаются ВСЕ комбинации. Причём РАЗНЫЕ комбинации.

Ноль тут при том, что единица == это модуль в степени 0. Вот с ним и получается неоднозначность. Даже если этот модуль — бесконечный. Но эта неоднозначность ни на что не влияет, только где-то в бесконечности. Потому и int'ы хорошо работают, пока мы не приблизились к модулю.

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

Кольца классов вычетов - это в точности все факторкольца натуральных.

для сложения только. Потому-что кольцо != поле.

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

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

ты тоже забыл слово «однозначно».

И потом, дурак — ты. Да, над множеством вычетов по модулю чего-то можно построить поле. Да, там можно определить «умножение». Да, оно даже будет однозначным(если модуль q^m). НО! Кто тебе сказал, что это ТАКОЕ ЖЕ УМНОЖЕНИЕ как для целых? Википедики? Дык кто же изучает математику по википедии?

С чего вдруг? Если что-то умножить на ноль - это всегда ноль. Вполне однозначно. Сможешь опровергнуть контр-примером?

речь не про возможность, а как раз наоборот — про неоднозначность. Проблема не в отсутствии возможности, проблема в том, что их МНОГО. И они НЕОТЛИЧИМЫЕ. Особенно если твой модуль == произведение чего-то. Но даже если модуль == простое число, то даже в этом случае произведение получается однозначным только для бесконечности. Если это то самое произведение, которое в школе проходят, и которое в твоём компьютере.

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

Попробуй таки составить эту таблицу умножения

#include <cstdio>

int main() {
    const size_t n = 256;
    using byte = unsigned char;
    for (size_t x = 0; x < n; ++x)
        for (size_t y = 0; y < n; ++y)
#ifdef E
            printf("%lu * %lu = %lu\n", x, y, x * y % n);
#else
            printf("%hhu * %hhu = %hhu\n", byte(x), byte(y), byte(byte(x) * byte(y)));
#endif
}
➜  ~  cxx -DE z.cc && ./a.out > 1 && cxx z.cc && ./a.out > 2 && diff 1 2
➜  ~  

ЧЯДНТ?

Ну и деление — сишные / и % на вычетах вполне определяются, как и деление в вычетах на сишных числовых типах, просто это разные вещи.

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

нету под рукой.

А что по алгебре у тебя есть под рукой?

проблема в том, что команда mul твоего CPU использует ДРУГУЮ таблицу умножения. В которой 2**8 получается таки 0 по модулю 256, а вовсе НЕ 29, как в поле Галуа.

Ну ага, получается как в кольце вычетов. Это ты поля Галуа зачем-то притянул, а я тебе сразу сказал, что там умножение происходит совершенно по-другому. Более того, как-то адекватно ассоциировать с элементами поля Галуа (в отличии от вычетов) для степеней >1 натуральные числа вообще нельзя - т.к. это многочлены над вычетами.

Произведения двух вычетов ложатся только НА НЕКОТОРЫЕ точки.

Ну да. Как и у интов. Произведение от этого не становится неоднозначным.

Ноль тут при том, что единица == это модуль в степени 0. Вот с ним и получается неоднозначность. Даже если этот модуль — бесконечный. Но эта неоднозначность ни на что не влияет, только где-то в бесконечности. Потому и int'ы хорошо работают, пока мы не приблизились к модулю.

Какая неоднозначность? Ты так и не привел пример, где умножение вычетов неоднозначно.

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

для сложения только. Потому-что кольцо != поле.

Для всего.

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

ты тоже забыл слово «однозначно».

«однозначно» в этих определениях никто не говорит, потому что любую операция _по определению и так однозначна_. Незачем повторять одно и то же по нцать раз. Взятие обратного элемента - операция, по-этому она однозначна. Так что все прекрасно у нас с полями, есть они.

Да, над множеством вычетов по модулю чего-то можно построить поле.

Можно. Но не нужно.

Да, там можно определить «умножение»

Умножение определяется в любом кольце.

НО! Кто тебе сказал, что это ТАКОЕ ЖЕ УМНОЖЕНИЕ как для целых?

Оно такое же как для целых, если результат меньше модуля. Определение у него такое. умножение в кольце Z_n определяется как [x]*[y] = [x*y] mod n

речь не про возможность, а как раз наоборот — про неоднозначность.

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

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

Умножение определено лишь в бесконечном поле целых и вещественных чисел

В поле Галуа умножение тоже частично определено, но ПО ДРУГОМУ

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

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

ЧЯДНТ?

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

Ну и деление — сишные / и % на вычетах вполне определяются

я говорил о том, что нет однозначности. Если ты это считаешь «определением» — всё в порядке.

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

Более того, как-то адекватно ассоциировать с элементами поля Галуа (в отличии от вычетов) для степеней >1 натуральные числа вообще нельзя - т.к. это многочлены над вычетами.

числа — тоже многочлены: 123=10^2+2*10^1+3*10^0

Поля Галуа — тоже многочлены, да. Как и числа. Но другие.

Ну да. Как и у интов. Произведение от этого не становится неоднозначным.

увы. Становится. Одних нулей получается слишком много. Не дело это, когда умножение двух не нулей даёт нуль. Это нарушение логики. А всё равно, в int'ах sqrt(M)*sqrt(M)==0. Ну и других таких не однозначностей тоже много.

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

ну вот выше. Для uint8_t 16*16==0. Мало?

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

При чем тут вложение, если речь о включении?

при том, что вложение - это включение с точностью до изоморфизма

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

ты пропустил слово «однозначно». Без него твоё «определение» не годно даже для того, что-бы им подтереться. Однозначно.

в кольце однозначно определено произведение элементов

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

Всё. В не поле не определено умножение и деление. Оно не нужно на практике. В вычетах определено лишь сложение. (да и то со многими оговорками)

Прекращай. Ну зачем ты так упорно пишешь глупости и продолжаешь спорить?

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

сиё есть бред и мечта. Доказательство опубликовано Кнутом более 30 лет назад.

Дай ссылку. Мне действительно интересно, что конкретно Кнут доказал. Понятно же, что математический результат не может звучать как «GC сливает malloc/free»

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

Не понял. Пусть будет вообще не size_t, а неограниченный nat_t, считаем, что байт восьмибитный — берём все пары чисел (x, y) : nat_t * nat_t таких, что x и y < 256, и получаем x * y < 256 (операция из Z/256Z) для каждой пары как (x * y) % 256 (операции из N). Потом берём эти x и y и преобразуем в byte(x) и byte (y) (< 256, так что никаких переполнений), так что byte(byte(x) * byte(y)) даёт ровно то же число (< 256, тут нет переполнения — работает остаток от деления по модулю, ищи в стандарте си или плюсов по слову «modulo», например «Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2 n where n is the number of bits in the value representation of that particular size of integer.»), что и (x * y) % 256.

То есть структура <byte, operator+, operator-, operator*> изоморфна структуре Z/256Z.

Структура <byte, operator+, operator-, operator*, operator/, operator%> изоморфна Z/256Z на которой определены функциональные отношения целочисленного деления и остатка от такого деления (и если выкинуть ноль, то тотальные функциональные отношения, то есть функции).

Также, на Z/256Z определено функциональное отношение деления как обратной операции к функции умножения — оно же определяется и на byte, так что опять получается изоморфизм структур.

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

Для беззнаковых типов другой битности — аналогично.

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

Я верю в тебя, бро. ты сможешь

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

тут нет переполнения — работает остаток от деления по модулю, ищи в стандарте си или плюсов по слову «modulo», например «Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2 n where n is the number of bits in the value representation of that particular size of integer.»

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

Итого, везде используются функции и функциональные отношения, то есть «_один_ результат

хрен с вами. Определили. Согласен. Теперь пользуйтесь своим «умножением», я не против.

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

Мне действительно интересно, что конкретно Кнут доказал. Понятно же, что математический результат не может звучать как «GC сливает malloc/free»

читай главу про менеджеры памяти. Она коротенькая.

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

в кольце однозначно определено произведение элементов

только там «умножение» хуже md5. Ибо md5 хотя-бы перебором можно обратить. А это твоё «умножение» НИКАК. Но я повторяю — это ваша проблема.

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

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

Ты тупой чтоли? Тебе специально, долбоебу, процитировали стандарт сишки, в котором сказано, что при переполнении результат считается modulo n^32

Что тебе еще надо, уебку?

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

Это и есть переполнение

Там дальше написано

This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type.

И ещё

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [ Note: most existing implementations of C ++ ignore integer overflows.

В случае беззнаковых операции и mathematically defined, и in the range, причём mathematically defined они через shall obey the laws of arithmetic modulo 2^n (ну то есть вычеты, даже англоязычная вики про integer overflow упоминает про них).

З.Ы. http://stackoverflow.com/q/18195715

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

анончик, успокойся. Никто не обещал, что в сишечке ПОЛЕ. Или «кольцо вычетов». Нет там ни того, ни другого. А «по модулю» только сложение/вычитание.

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

Это и есть переполнение, которое ты не учитываешь. Потому у тебя ерунда и получается.

ignore integer overflows.

кто из нас «тупой»?

В случае беззнаковых операции и mathematically defined, и in the range, причём mathematically defined они через shall obey the laws of arithmetic modulo 2^n (ну то есть вычеты, даже англоязычная вики про integer overflow упоминает про них).

и тем не менее, в кольце вычетов умножение не определено. А то, что у тебя, в русской вике «определено», — хрень полная. Не лезет произведение в такой же размер. Ему вдвое больше бит надо. В процессоре 8086 и выше, именно так и сделано. А в сишечке — обрезали. Получилась ерунда.

«Вычеты» определены для сложения. Оно да, по модулю 2*MAX_INT работает.

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

ignore integer overflows

Ну да, когда оно есть. А про беззнаковые числа сказано, что его нет, есть поведение арифметики по модулю — если результат (сложения, вычитания, умножения — http://stackoverflow.com/q/7221409, http://stackoverflow.com/q/9193880, http://en.cppreference.com/w/cpp/types/numeric_limits/is_modulo (!), http://www.cs.utah.edu/~regehr/papers/overflow12.pdf) не влезает, то берётся остаток от деления по модулю, в арифметике вычетов ситуация точно такая же — http://en.wikipedia.org/wiki/Modular_arithmetic#Integers_modulo_n (так же — сложение, вычитание, умножение).

в кольце вычетов умножение не определено

http://en.wikipedia.org/wiki/Modular_arithmetic#Integers_modulo_n [2]

Ну и если это кольцо, то как там может быть не определено умножение?

Не лезет произведение в такой же размер

Лезет оно — есть два числа < 2 ^ n, их результат тоже < 2 ^ n.

В процессоре 8086 и выше, именно так и сделано. А в сишечке — обрезали.

Вот и напиши сюда пример с imulq который бы вёл себя не так как умножение Z/(2^64)Z.

«Вычеты» определены для сложения

Если ты ок с тем, что max_unsigned + 1 = 0 это вполне себе «сложение» (но «не лезет» же), то умножение — тоже вполне себе «умножение». В любом случае, это всегда x # y = (x #N y) % (2 ^ n).

Оно да, по модулю 2*MAX_INT работает.

max_unsigned + 1 = 2 ^ n, если знаковые работают, то это будет 2 * (max_signed + 1) = 2 * |min_signed| = 2 ^ n — http://igoro.com/archive/why-computers-represent-signed-integers-using-twos-c....

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

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

слова «в кольце X умножение не определено» не имеют смысла

умножение беззнаковых нормально работает

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

Ну да, когда оно есть. А про беззнаковые числа сказано, что его нет, есть поведение арифметики по модулю — если результат (сложения, вычитания, умножения

ну повторяю ещё раз: если есть переполнение (а в общем случае оно есть с вероятностью 4294967295/4294967296, т.е. практически 100%, при условии равномерного распределения аргументов), то результат умножения НЕ ОПРЕДЕЛЁН. То, что есть — как определение не годится, ибо является неоднозначным по аргументам. Это просто последовательность действий, которая даёт результат. И этот результат абсолютно бесполезен. Ну да, для фиксированных аргументов «произведение» однозначно. Может таки расскажешь, ЗАЧЕМ нужно это «произведение»? А то мне, IRL, приходится переходить к верхнему типу вроде uint64_t, что-бы туда загрузить произведение. А затем его оттуда по частям вынимать. Потому-что, даже если мне наплевать на точность, мне нужна *старшая половина*, а никак не младшая. Единственное, зачем нужна младшая — генерировать кривенькие псевдослучайные числа, в которых большая часть битов совсем не случайная, да и само число вполне себе предсказуемо. Есть ещё применения ЭТОЙ «арифметики»? Ну ты скажи, а то я не в курсе.

в кольце вычетов умножение не определено

http://en.wikipedia.org/wiki/Modular_arithmetic#Integers_modulo_n [2]

да. Есть «определение», но оно не годное. Если по твоему «годное», расскажи — для чего.

Ну и если это кольцо, то как там может быть не определено умножение?

однозначно не может быть определено. Куча эл-тов не имеет обратного эл-та по умножению. Т.е. эта твоя «определённость» напоминает дуршлаг. Грубо говоря, ты звонишь по телефону, и говоришь «я стою на дороге, и передо мной указатель „Москва -->“. ». Твоё местоположение определено? Таких указателей по России 100500. точно также и «определено» твоё «умножение».

Лезет оно — есть два числа < 2 ^ n, их результат тоже < 2 ^ n.

Иди в школу. 2^n * 2^n == 2^(2*n).

Вот и напиши сюда пример с imulq который бы вёл себя не так как умножение Z/(2^64)Z.

http://www.cs.cmu.edu/~fp/courses/15213-s07/misc/asm64-handout.pdf там ответ в %rdx:%rax. Т.е. биты с 64го по 127й лежат в %rdx. В сишечке они просто выкидываются.

И такая фигня ещё с i8086.

Если ты ок с тем, что max_unsigned + 1 = 0 это вполне себе «сложение» (но «не лезет» же)

лезет жеж! Никаких «дыр» нет в принципе, и единственная неоднозначность, которую мы имеем — один единственный бит (он связан с тем, что 2+7==7+2. Из за этого информация при сложении немножко теряется, потому-что работает переместительный закон, который и даёт неоднозначность. В итоге получается, что разрядность суммы на один бит больше). Но вот если одно из слагаемых фиксировано, и его энтропия равна нулю, то результат однозначный, т.е. энтропия не увеличивается. Например у increment'а 8и битного числа РОВНО 256 результатов, и КАЖДЫЙ из них ОДНОЗНАЧНО обращается. По этой причине, сложение определено ОДНОЗНАЧНО. В модулях — тоже. А вот умножение — увы.

то умножение — тоже вполне себе «умножение». В любом случае, это всегда x # y = (x #N y) % (2 ^ n).

это младшая половина результата. Кому и зачем она нужна — я не знаю. Лично мне приходится ограничиваться sqrt(M), в таком кусочке всё работает правильно.

max_unsigned + 1 = 2 ^ n, если знаковые работают, то это будет 2 * (max_signed + 1) = 2 * |min_signed| = 2 ^ n

я в курсе. К чему это ты?

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

слова «в кольце X умножение не определено» не имеют смысла

не «в кольце», а в вике. Там написано, что «определено», и это правда — _можно_ определить, например в поле Галуа. Или если у тебя результат не по модулю M, а по модулю M*M.

И да, сам подумай: если ты метры множишь на метры, то у тебя получаются в ответе *квадратные* метры. А почему модуль таким и остаётся? Какое ты имеешь право выносить модуль за скобки умножения?

умножение беззнаковых нормально работает

ну только в статье из википедии.

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

Какое ты имеешь право выносить модуль за скобки умножения?

лолшто?

умножение беззнаковых нормально работает

ну только в статье из википедии.

да нормальное там умножение по модулю.

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

Лично мне приходится ограничиваться sqrt(M), в таком кусочке всё работает правильно.

Т.е. ты развёл всю эту богодельню вот из-за этого правила, которое мне объясняли ещё на первом курсе, когда в школе даже не знали слова «информатика»?

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

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

Т.е. ты развёл всю эту богодельню вот из-за этого правила, которое мне объясняли ещё на первом курсе, когда в школе даже не знали слова «информатика»?

ну типа да.

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

удивительно то, что 95% этого правила всё равно никогда не поймут... И будут искренне уверены, что их няшный питончик таки считает «правильно». Вот и вика тоже — гарантирует...

PS: шутка удалась лишь на 10й странице. Печально... Лет десять назад меня-бы поймали в 10 раз быстрее... Куда катится мир?..

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

И будут искренне уверены, что их няшный питончик таки считает «правильно».

А в питоне при «переполнении» разве автоматически не возвращается ответ в «больших числах»? Или это я по лиспу теперь всю динамику сужу? )))

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

Какое ты имеешь право выносить модуль за скобки умножения?

лолшто?

данишо. Не лолкай, лоли. Иди лучше в школу, спроси училку про модули, она объяснит. А вику больше не читай. Это энциклопедия, а не учебник.

да нормальное там умножение по модулю.

детка, компьютер нужен для обработки информации. Инструменты этой обработки называются «операторами». В них не должно быть дырок, а если они есть, их должно быть немного, что-бы можно было их затыкать. Т.е. оператор не должен быть решетом, которое в принципе не заткнуть. Т.е., если информация даже теряется, то надо ТОЧНО знать, КАК, КОГДА, и СКОЛЬКО. Вот в твоём «умножении» теряется ПОЛОВИНА результата, потому оно годно лишь для создания кривого рандома. И кривой он кстати как раз именно из-за этих потерь. Даже самый лучший генератор ПСЧ из 32х бит теряет 99.6% случайности. Т.о. оно даже для рандома не годно.

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

А в питоне при «переполнении» разве автоматически не возвращается ответ в «больших числах»?

ой, да. Это я ошибся — вот питон как раз возвращает. Мой даже 2**128 посчитал. Т.ч. там нормальная арифметика.

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

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

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

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

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

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

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

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

В случае вычетов, как минимум:

1. Любая f : ℤ × ℤ → ℤ со свойством ∃ n f₁ f₂. ∀ a b k l. f(a + k * n, b + l * n) = f₁(a, b, n) + f₂(a, b, k, l, n) * n обобщается с ℤ на ℤ/nℤ как f′ : ℤ/nℤ × ℤ/nℤ → ℤ/nℤ; f′([a], [b]) = [f₁(a, b, n) % n].

2. ⟨ℤ/nℤ, f′⟩ ≊ ⟨n ‌? [0, n) : ℤ, λ a b → f₁(a, b, n) % n⟩.

3. «Обобщается», так как при n = 0 получаем ℤ/0ℤ ≊ ℤ, f = f₁, f′([a], [b]) = [f(a, b)], ⟨ℤ/0ℤ, f′⟩ ≊ ⟨ℤ, f⟩.

4. +, ─ и * обладают свойством (1), так что ⟨ℤ/nℤ, +′, ─′, *′⟩ ≊ ⟨n ? [0, n) : ℤ, λ a b → (a + b) % n, λ a b → (a ─ b) % n, λ a b → (a * b) % n⟩.

2^n * 2^n == 2^(2*n).

Так мы в вычетах умножаем или где? «< 2 ^ n», ну и % (2 ^ n) на результате делать нужно, либо сдвигать на n.

В сишечке они просто выкидываются.

Что эквивалентно сдвигу, что эквивалентно взятию остатка по модулю от результата, то есть относительно {8, 16, 32, 64}-битных регистров мы получаем в точности умножение ℤ/(2^{8, 16, 32, 64})ℤ. А то речь шла про «это не вычеты» и «в вычетах нет умножения».

К чему это ты?

Опечатка у тебя там была.

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

детка, компьютер нужен для обработки информации. Инструменты этой обработки называются «операторами». В них не должно быть дырок, а если они есть, их должно быть немного, что-бы можно было их затыкать. Т.е. оператор не должен быть решетом, которое в принципе не заткнуть. Т.е., если информация даже теряется, то надо ТОЧНО знать, КАК, КОГДА, и СКОЛЬКО. Вот в твоём «умножении» теряется ПОЛОВИНА результата, потому оно годно лишь для создания кривого рандома. И кривой он кстати как раз именно из-за этих потерь. Даже самый лучший генератор ПСЧ из 32х бит теряет 99.6% случайности. Т.о. оно даже для рандома не годно.

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

Где-то так:

unsigned char a = 150;
unsigned char b = 210;
unsigned char r = 15*b-20*a
Waterlaz ★★★★★
()
Ответ на: комментарий от quasimoto

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

ок, согласен.

но там ближе к началу я это уже говорил. Задолбало.

Что эквивалентно сдвигу, что эквивалентно взятию остатка по модулю от результата

...что эквивалентно ПОТЕРЕ информации. Т.е. это не просто «обычное умножение», это «необратимое умножение». Разница тут ИМХО принципиальная. Потому как на практике подразумевается, что раз мы помножили на x, то и поделить на x сможем, если конечно x не является «ничем».

Но в теории — да, возможно конструирование неких абстрактных правил, в которых будет некое абстрактное «умножение», для которого это не подразумевается.

Вот только я всё равно не понимаю, нахрена оно нужно?

Можно придумывать бесконечно много правил, которые никому не нужны. В этом разве есть смысл?

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

У меня гарантированно будет правильный ответ.

позволь узнать, ЗАЧЕМ тебе нужен такой ответ? На практике, если мы что-то на что-то умножаем, то в конце нам ещё и поделить надо. Вот тут-то нам и понадобятся старшие биты, которые ты потерял. Терять-то надо именно младшие биты, а никак не наоборот, потому-что их ценность — либо такая же, либо ниже. Информация в битах произведения распределена неравномерно: в нулевом бите содержится смесь нулевых битов, в первом бите — смесь нулевых и первых, и так далее. Т.е. чем старше бит, тем от большего количества бит он зависит. Если ты сохранил старшие биты, то ты примерно знаешь интервал, в котором лежит истинное произведение, если сохранил младшие биты, то ты знаешь точно расстояние от модуля, умноженного на какое-то неизвестное число(которое ты потерял). Вот я и спрашиваю: ЗАЧЕМ тебе это расстояние? Какой в нём вообще физический смысл? Есть хоть одно явление в этом мире, которое характеризуется таким числом?

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

unsigned char r = 15*b-20*a

Если я знаю, что результат помещается в мой беззнаковый тип

теперь нарисуй мне ПРОВЕРКУ того, что оно действительно помещается. А то мне этот момент не совсем ясен в твоём коде. Если я все числа ЗНАЮ, то зачем вообще заставлять компьютер считать? А если не все, то какие именно я НЕ знаю? И как получилось, что я, не зная результат, знаю, что он куда-то влезает?

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

А еще такой вот swap всегда корректно работает для unsigned

есть только три проблемы:

1. а это unsigned?

2. код намного медленнее, чем имеющееся практически везде машинная инструкция. И я не представляю настолько гениальный компилятор, который это распарсит. Такое и программист не каждый поймёт(если не в курсе).

3. код очевидно не подходит для многозадачных систем.

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

Вот только я всё равно не понимаю, нахрена оно нужно?

Представь себе - для того, чтобы умножать. При этом деление может и не быть вовсе. Потому что нам надо умножать - не делить. Умножать надо. А делить - не надо.

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

На практике, если мы что-то на что-то умножаем, то в конце нам ещё и поделить надо.

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

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

∃ n f₁ f₂. ∀ a b k l. f(a + k * n, b + l * n) = f₁(a, b, n) + f₂(a, b, k, l, n) * n

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

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

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

Это стандартная запись, хз, так все пишут вплоть до 80-летних преподавателей по матану. Ну разве что обычно двоеточия, а не точки, и запятые ставят

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

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

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

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

теперь нарисуй мне ПРОВЕРКУ того, что оно действительно помещается. А то мне этот момент не совсем ясен в твоём коде. Если я все числа ЗНАЮ, то зачем вообще заставлять компьютер считать? А если не все, то какие именно я НЕ знаю? И как получилось, что я, не зная результат, знаю, что он куда-то влезает?

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

Типичная подзадача, возникающая просто на кажждом ходу, например, в обработке изображений:

Есть массив неотрицательных чисел a[n][m]. Необходимо периодически вычислять суммы этих чисел на прямоугольниках:

s(n1, n2, m1, m2) = \sum_{n1<=k<=n2, m1<=j<=m2}a[k][j]

Решение: предварительно вычисляем числа S(x, y) = s(0, x, 0, y)

тогда s(n1, n2, m1, m2) = S(n2, m2)+S(n1, m1)-S(n1, m2)-S(n2, m1)

Как правило, нам нужны суммы прямоугольников небольших площадей(скажем, 10х10), которые вполне помещаются в наш беззнаковый тип. При этом числа S(x, y) могут быть очень большими и не влазить

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

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

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

Но для меня это где-то на уровне азбуки в информатике. И мне всё равно не понятно, как один умудрился раздуть из мухи слона, а другие повелись на этот троллинг... :\

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

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

Решение: предварительно вычисляем числа S(x, y) = s(0, x, 0, y)

а вот так палятся люди, которые в состоянии лишь нагуглить формулу, и скопипастить её в свой код...

Ладно, объясняю, как это работает: у тебя вычисления предварительные здесь. Т.е. ты выносишь инвариант из цикла. А именно — дорогое умножение выносишь наружу, вычисляя его предварительно. Это и есть твои S(x,y). Фишка тут в способе хранения этих S, т.к. они очень похожи(S(x,y1) ~= S(x,y2)), ты хранишь не сами площади, а их разности. Это широко известное дельта кодирование. И естественно не целиком, а только младшие биты. Не слишком надёжно(ибо вообще говоря никто не обещал, что все дельты будут меньше M, это просто маловероятно, что их будет «много»), но для графики к тупой гаме — потянет. Подумаешь — небольшие артефакты...

Я так часто делаю, но в отличие от тебя, я использую не «младшие M битов», а специальный код переменной длинны, например Хаффмана.

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

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

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

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

ИМХО основной косяк не в этом, а в том, что алгоритм сам по себе ошибочный. Это типичное «сжатие с потерями», когда любая музыка приводится к модели «зайка моя.mp3», а всё, что не лезет, нещадно обрезается. Да, быстро, и да, жмёт хорошо. И да, «зайка моя.mp3» звучит не хуже, чем на живом концерте Ф.Киркорова. (:

В принципе, подход имеет смысл, если данные более-менее одинаковы, и если подобрать эмпирические константы для нормализации данных в пространство вычислителя, так, что-бы нам надо было хранить именно M битов модуля. Потому-что тут мы считаем не так, как надо, а так, как нам _удобнее_.

И мне всё равно не понятно, как один умудрился раздуть из мухи слона, а другие повелись на этот троллинг...

это ЛОР.

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

Ну да. И еще пишут типы переменных и функций.

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

Во-первых, на всём пространстве задач данная таки сверх-узко-специализированная

Просили пример, получили пример. В других областях есть другие задачи.

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

ИМХО основной косяк не в этом, а в том, что алгоритм сам по себе ошибочный.

Не ошибочный.

Это типичное «сжатие с потерями»

Никаких потерь нет.

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

Ладно, объясняю, как это работает: у тебя вычисления предварительные здесь. Т.е. ты выносишь инвариант из цикла. А именно — дорогое умножение выносишь наружу, вычисляя его предварительно.

Я нигде не вычисляю умножение. Его тут нет в принципе.

Фишка тут в способе хранения этих S, т.к. они очень похожи(S(x,y1) ~= S(x,y2)), ты хранишь не сами площади, а их разности. Это широко известное дельта кодирование.

Нет. Фишка тут вовсе не в этом, а в быстром вычислении суммы(за время не зависящее от размера прямоугольника, на котором вычисляется сумма).

Я так часто делаю, но в отличие от тебя, я использую не «младшие M битов», а специальный код переменной длинны, например Хаффмана.

Ну и дурак, Хаффман тут ни при чем.

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

Но для меня это где-то на уровне азбуки в информатике. И мне всё равно не понятно, как один умудрился раздуть из мухи слона, а другие повелись на этот троллинг... :\

Троллинг? Никто же не спорит, что для представления произведения двух n-битных чисел нужно 2*n бит. Мне не нравятся другие ошибочные его утверждения

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

Нет. Фишка тут вовсе не в этом, а в быстром вычислении суммы(за время не зависящее от размера прямоугольника, на котором вычисляется сумма).

С быстрым вычислением не понятно: как вычисление 4-х сумм размерностью x000*y000 может быть быстрее вычисления одной суммы n*m, пусть и «глубоко в матрице»?

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

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

Все суммы S(x, y) можно вычислить за линейное время от размеров изображения. После этого любая сумма s(n1, n2, m1, m2) вычисляется за константу.

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

Есть массив неотрицательных чисел a[n][m]. Необходимо периодически вычислять суммы этих чисел на прямоугольниках: s(n1, n2, m1, m2) = \sum_{n1<=k<=n2, m1<=j<=m2}a[k][j]

Я нигде не вычисляю умножение. Его тут нет в принципе.

ты действительно идиот, или теперь ты тут клоунаду устраиваешь?

Нет. Фишка тут вовсе не в этом, а в быстром вычислении суммы(за время не зависящее от размера прямоугольника, на котором вычисляется сумма).

ох...

Ну и дурак, Хаффман тут ни при чем.

абсолютно верно. Это тупой терминальный вариант кода Хаффмана, когда «лишние» биты тупо отрезаются. В нормальном коде, для каждого символа входного алфавита вычисляется код оптимальной длинны, а в твоём варианте ты тупо положил, что дескать «оптимальная длинна == M». Да, при некоторых допущениях оно даже работает. Криво, но для говнографики пойдёт.

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

А теперь представь что мне надо найти разность между двумя этими площадями. Каждая из них - больше 2^32, но разность - меньше.

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

но там ближе к началу я это уже говорил

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

Вот только я всё равно не понимаю, нахрена оно нужно?

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

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

А теперь представь что мне надо найти разность между двумя этими площадями. Каждая из них - больше 2^32, но разность - меньше.

представил. А зачем? Как так получилось, что площади больше 2^32, а разности — меньше? Откуда такое ПРАВИЛО? Ты из пальца высосал? Ну высасывай дальше...

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

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

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

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

угу. Фишка в том, что это искусственное ограничение, и к железу оно отношения НЕ имеет. Эти ваши вычеты никому IRL не нужны, и потому их никто и никогда не реализовывал в железе. Ну просто нет смысла умножать 3/4 мусора, который ни на что не влияет. В сишечку оно попало лишь для совместимости и кроссплатформенности. Подразумевалось, что эти int'ы — исключительно индексы, произведения индексов — суть матрицы, а матрицы не могут быть больше регистра адреса. Ибо меньше char'а чисел не бывает. Потому-то int'ы никогда и не должны переполняться. Если же тебе нужна действительно целая арифметика — обмазывайся ассемблером. Она в принципе не переносима. Наверное из этих соображений K&R подложили такую свинью.

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

Типизация там не нужна, так как тип f уже был озвучен — кроме целых чисел и функций на них там ничего не может быть.

Остальное ок? А то там ещё тернарный оператор, чтобы не считать, что расходящийся интервал совпадает с множеством на котором задаётся (в дополнение к изоморфизму Z и Z/0Z и x % 0 = x).

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

просто ты их не видишь. Ибо не понимаешь, как это работает.

Нет там потерь. Я n*m чисел кодирую другими n*m чисел, по которым исходные можно восстановить внезависимости от того, было там переполнение или нет.

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

ты действительно идиот, или теперь ты тут клоунаду устраиваешь?

Оператор умножения я нигде не использую. Так что скажи мне, что на что я умножаю там?

Это тупой терминальный вариант кода Хаффмана, когда «лишние» биты тупо отрезаются.

ты любое кодирование называешь «вариант кода Хаффмана»? :D

В нормальном коде, для каждого символа входного алфавита вычисляется код оптимальной длинны, а в твоём варианте ты тупо положил, что дескать «оптимальная длинна == M»

Ничего подобного я и близко не делал. Никаких оптимальных длин не предполагал.

Еще раз. У меня был массив беззнаковых n*m чисел a[x][y]. Я из него построил массив беззнаковых n*m чисел s[x][y], из которого:

во-первых, однозначно и без потерь можно восстановить исходный массив a[x][y]

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

Если ты с этим не согласен, то либо неправильно понял то, что я делаю, либо не понимаешь, как работает unsigned арифметика.

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

Как так получилось, что площади больше 2^32, а разности — меньше?

Очень легко. А в чем проблема с тем, чтобы так получилось?

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

Нет, я не спорю с записью, просто интересуюсь.

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

Оператор умножения я нигде не использую. Так что скажи мне, что на что я умножаю там?

школьного курса арифметики для этого похоже не хватит. Извини.

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

школьного курса арифметики для этого похоже не хватит. Извини.

Слив защитан?

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

Т.е. ты выносишь инвариант из цикла.

Если и выношу, то уж точно не инвариант.

А именно — дорогое умножение выносишь наружу, вычисляя его предварительно.

В приведенном мною примере умножения нет вовсе.

Это и есть твои S(x,y).

S(x, y) — всего лишь суммы a[k][j], 0<=k<=x, 0<=j<=y

Фишка тут в способе хранения этих S, т.к. они очень похожи(S(x,y1) ~= S(x,y2)), ты хранишь не сами площади, а их разности.

Я храню не площади и уж тем более не их разности, а суммы по модулю некоторого числа.

Это широко известное дельта кодирование.

Это не дельта кодирование.

И естественно не целиком, а только младшие биты. Не слишком надёжно(ибо вообще говоря никто не обещал, что все дельты будут меньше M, это просто маловероятно, что их будет «много»), но для графики к тупой гаме — потянет. Подумаешь — небольшие артефакты...

Соответственно, вот это все бред.

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

О какой функции идет речь? В моем примере ни о какой функции речь не шла.

Waterlaz ★★★★★
()
Последнее исправление: Waterlaz (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.