- 1
- 2
- 3
for(x = 1; x; x += x)
if(!(((e*x)%m)/t))
{ x = d; break; }
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+111
for(x = 1; x; x += x)
if(!(((e*x)%m)/t))
{ x = d; break; }
Недавно прислали с вопросом: "Тут что-то поломалось, надо исправить... Поможешь?"
Lure Of Chaos 30.11.2011 16:27 # 0
roman-kashitsyn 30.11.2011 16:29 # +4
это пять!
ling 30.11.2011 17:54 # +4
roman-kashitsyn 30.11.2011 18:01 # 0
bugmenot 30.11.2011 18:03 # 0
7ion 01.12.2011 00:08 # +3
zoggi 01.12.2011 13:13 # 0
TarasB 01.12.2011 13:35 # 0
roman-kashitsyn 01.12.2011 13:41 # 0
TarasB 01.12.2011 13:50 # −1
roman-kashitsyn 01.12.2011 13:54 # +5
TarasB 01.12.2011 14:36 # −2
А, это же КРЕСТЫ, тут нет модульных типов...
defecate-plusplus 01.12.2011 15:11 # +1
оказалось банально
"Таким образом, модульные типы Ада соответствуют целочисленным беззнаковым типам в других языках программирования (например: Byte, Word... - в реализациях Паскаля; unsigned short, unsigned... - в C/C++)."
я верно понял, что в аде целое число либо знаковое, либо "модульное"?
TarasB 01.12.2011 15:43 # +5
Хорошо, что я успел ответить, а то чуть новый миф не родился ("ололо, в Аде нет беззнаковых типов с контролем переполнения").
Помню, я на гдрушечке сказал, что в Паскале ГСЧ инициализируется текущим временем при помощи функции Randomize, так там один тип сразу же вывел из этого, что стандартный паскалевский ГСЧ нельзя инициализировать своим значением.
Вообще логика крестушков поражает.
Скажешь им, что паскалевский case (аналог switch) позволяет указывать диапазоны и перечисления - они в ответ заявляют, что он не умеет оптимально искать число и что там делается тупо цепочка else if. Да, тоже на гдрушечке.
Сегодня один хрен бездоказательно вывел, что якобы Дельфи не умеет убивать ветки, которые никогда не выполнятся. Да, тоже на гдрушечке.
bugmenot 01.12.2011 16:00 # +2
Да это же не типичные крестушки, а просто типичные полуебки. 95% процентов всего этого бессвязного лепета решается прочтением документации, где многа букав, да. Такие говноспоры можно решить парой встречных вопросов по поведению крестов и они сразу поджимают хвосты, потому что в своем любимом инструменте аналогично слабо разбираются.
defecate-plusplus 01.12.2011 16:03 # 0
с какого то первого попавшегося мануала, который мне на пальцах рассказал, зачем в аде отдельная сущность с отдельным названием "модульный целочисленный тип"
http://www.ada-ru.org/V-0.4w/part_1/ch_02.html
еще цитата, оттуда же
"Стандарт Ada95 разделяет целочисленные типы на целые числа со знаком и модульные типы. По существу, модульные типы являются целыми числами без знака. Характерной особенностью таких типов является свойство цикличности арифметических операций."
контроль переполнения на каждый чих - оверкилл какой то
рождать новые мифы не собираюсь - модульных типов в С++ нет, есть человеческие беззнаковые целые типы, занимающие ровно столько пространства, сколько требуется для обеспечения максимального быстродействия
предугадывая твои вопросы - мне не сложно в С++ написать микрокласс над стандартным типом, который бы отслеживал свои переполнения без ассемблера, а для некоторых диапазонов (- 2 ** i .. 2 ** i, где i <=6, 14, 30, 62) оверхед был бы даже наноскопическим, но что то как то не было нужды
TarasB 01.12.2011 16:09 # 0
Непонятно. Можно задать тип с контролем переполнения с любым диапазоном. Хоть со знаком, хоть без, хоть вообще от -5 до +9000.
> контроль переполнения на каждый чих - оверкилл какой то
> а для некоторых диапазонов (- 2 ** i .. 2 ** i, где i <=6, 14, 30, 62) оверхед был бы даже наноскопическим
Так оверкилл или наноскопия?
Зато не надо проверять контроль диапазона для индекса массива, если переменная, которой итерируем, принадлежит типу, являющемся диапазоном массива.
Контроль ошибки переполнения меня спасал не раз, если что.
Ну и напоследок - если понадобится скорость, то берётся узкое место, тщательно проверяется и в нём (локально в одной процедуре) убираются проверки.
defecate-plusplus 01.12.2011 16:18 # 0
но тем не менее при любых арифметических операциях с этим типом будут производиться проверки, когда как такие проверки обычно нужны только один раз - когда они реально собираются влиять на что то
проверка границ массива - обычно забота массива
но этот оверкилл был намеренно заложен в аду, для надежности, так что ничего против не имею
для справки - в аде можно создать тип из границ, известных только во времени выполнения?
TarasB 01.12.2011 16:31 # 0
2 разряда на знак? Нафига. Что-то был в Окамле такой косяк, помнится.
В Аде тип integer работает без этого.
> но этот оверкилл был намеренно заложен в аду, для надежности
Это другой подход к проверкам. И иногда он даёт ускорение.
for i in A'Range loop
s:=s+A(i); // тут не делается проверка на вхождение, так как итак i принадлежит типу A'Range
end loop;
Кстати, в Дельфи так же. И тут Пушков снова обломался, когда сказал, что в Дельфи делается проверка на вхождение в диапазон массива. Так вот хрен. Если
a: array [Smth] of integer;
i: Smth;
То в
a[i] проверка не делается.
Но Пушков, очевидно, проверял для i: integer;
Что делать, крестушки не умеют использовать на всю катушку особенности системы типов в паскалевом семействе.
> для справки - в аде можно создать тип из границ, известных только во времени выполнения?
Да, конечно. И массивы неизвестной длины, аллоцирующиеся на стеке. Иначе как будут работать шаблонные модули, инициализируемые параметрами, полученными при выполнении?
defecate-plusplus 01.12.2011 16:43 # 0
проверять регистров флагов (чего в С/С++ без использования ассемблера напрямую я не знаю как сделать) - возможно не на каждом процессоре этот регистр есть вообще, или просто выделить еще один разряд рядом со знаком, тогда 00,11 будут означать валидные +/- числа, а 01,10 - переполненные +/- числа
> a[i] проверка не делается
компилятору приходится всего лишь каждый раз вычислять offset из передаваемого аргумента, в отличие от C/C++, который перекладывает эти задачи на программиста
для статических проверок "из коробки" в С/С++ есть только упрощенный вариант с
typedef enum { elem0 = 0, elem1, elem2, elem3 } elem_idx_type;
int a[elem3 + 1];
elem_idx_type i = elem2;
a[i] - аналогично не сможешь выйти за границы
конечно не надо забывать, что для си что a[i], что *(a + i), что i[a] одно и то же - отдаст ячейку по смещению от адреса a и его не будут парить границы - и иногда это как раз удобно, есть такой трюк
а вот если в дельфи объявлено a: array [Smth] of integer;
компилятор ругается при a[200], если 200 не входит в диапазон?
TarasB 01.12.2011 17:20 # 0
Ну не знаю, ГНАТ, работающий ерез кроссплатформенный ГЦЦ, это не остановило.
> компилятору приходится всего лишь каждый раз вычислять offset из передаваемого аргумента
Ну и что? Лишь бы не программа.
> а вот если в дельфи объявлено a: array [Smth] of integer;
компилятор ругается при a[200], если 200 не входит в диапазон?
Ругается, но я не помню, в виде ошибки или предупреждения.
defecate-plusplus 01.12.2011 18:06 # 0
http://en.wikipedia.org/wiki/Overflow_flag
Instructions such as multiply and divide often leave the flag undefined, or affected by the last partial result.
так что врядли адовский компилятор опирается на флаги состояния процессора, поэтому у него остается два пути
1) для результата умножения A * B выделять место размером size(A)+size(B), отправлять на процессор делать умножение и потом смотреть влез ли результат в пользовательский диапазон - дешево, быстро, но ограниченно
2) попытаться в обход CPU сделать умножение по своим алгоритмам, в процессе определив переполнение - в принципе, вполне посильная задача, например, с помощью всем известного shift and add (и, фактически, на этот способ намекают ограничения по размерам целых типов в стандарте, который я нашёл)
generic programming в рантайме это бывает и неплохо, конечно
как ада разбирается с тем, что требуется вызвать конкретный метод у объекта, передаваемого как private?
TarasB 01.12.2011 18:25 # 0
Передавать в шаблоны "структура, у которой есть поле a", нельзя. Можно передавать "тип, для которого определены Get(T,a) и Set(T,a)".
3.14159265 01.12.2011 18:36 # 0
Я вот что-то не пойму. Язык Ада, он тобой в одних случаях классифицируется как высокоуровневый язык (в отличие от КРЕСТОВ синтаксис которых во многом завязан на низкоуровневость).
В других же, Ада напрямую привязана к процессорной реализации умножения.
TarasB 01.12.2011 18:54 # 0
Синтаксис Ады ни к чему не привязан.
Привязана реализация.
Будет другой проц - будет другая реализация.
3.14159265 01.12.2011 19:01 # +1
Из этого предложения я сделал вывод, что работа диапазонных типов Ады основана на специфике умножения в x86.
roman-kashitsyn 01.12.2011 19:04 # 0
3.14159265 01.12.2011 19:10 # 0
TarasB 01.12.2011 20:31 # 0
defecate-plusplus 01.12.2011 19:39 # 0
где то очевидные плюсы, а затем минусы, перекрывающие все плюсы
TarasB 01.12.2011 20:33 # 0
Это каким извращённым мозгом надо обладать, чтобы из описания потрохов одной реализации сделать вывод, что всё гвоздями прибито к этой реализации?
Давайте, я тоже потроллю.
В C под x86 сложение целых делается через add eax,edx (ну или другие два регистра), всё, значит C гвоздями прибит к x86, потому что его сложение опирается на архитектуру х86.
defecate-plusplus 01.12.2011 21:02 # 0
преимущества компайл-тайм шаблонов С++ - если тебе передали тип T, то ты с ним можешь вертеться как хочешь - хочешь обращайся к его полям, хочешь вызывай методы, хочешь используй объявленные в нем типы, константы, енумы - всё, до чего дотягиваются руки, хочешь наследуйся от него, объявляй на его основе другие типы
компилятор всё съест и если где то не срастётся - будет тебе жаловаться, потому что он разворачивает это всё и затем пытается взлететь
недостатки также очевидны
я почему спросил - к рантайм/гибридным дженерикам в разных языках разный подход, и в этом свете подход ады не выглядит самым удобным
тупо запретить любые телодвижения в влево/вправо - на тебе объект-черный ящик и крутись как хочешь. Если запрещено работать с объектом как с объектом, а разрешено с ним работать только как с куском памяти известного размера, то такой дженерик не намного отличается от передачи в виде аргументов void * и size_t оного - сделать контейнер элементов произвольного типа в рантайме, предоставляя доступ к каждому из элементов, методы его роста, можно даже на С - ты же на это ссылался, что можно на стеке создавать массивы переменной длины
если бы ты раскрыл в чем суть
> "тип, для которого определены Get(T,a) и Set(T,a)"
может моё мнение и изменилось бы
TarasB 01.12.2011 21:13 # 0
Причём под операциями подрузумеваются исключительно процедуры и функции (бинарные операторы тоже к ним относятся). А вот операция взятия поля с именем a к ним, увы, не относится, поэтому, если тебе это надо, ты можешь только передавать туда GetA и SetA.
И это не совсем как в Си, потому что передаваемый в шаблон функции могут инлайниться.
TarasB 01.12.2011 20:36 # 0
Да, ты скажешь, что это на крестах элмулируется, ну так это да, тьюринг-полнота.
Ну а чего ты такого ожидал от статически типизированного языка?
Да, так вот насчёт T.a.
Просто этого нет в концепции. Да и вообще, это не инкапсулятивненько.
3.14159265 30.11.2011 18:00 # +1
d в цикле не вычисляется.
что-то тут не чисто.
absolut 30.11.2011 23:28 # +2
dos_ 30.11.2011 18:04 # +5
Psionic 30.11.2011 19:23 # +4
SIGSEGV 30.11.2011 21:54 # +2
x = 8
m = 5
t = 3
сойдет?
TarasB 01.12.2011 09:55 # +2
Brand 01.12.2011 10:45 # 0
SIGSEGV 01.12.2011 10:58 # 0
Depriver 19.01.2012 15:12 # 0
d_dev 01.12.2011 13:17 # −2
Nemoden 01.12.2011 14:03 # +7
мой мозг.