Есть такой момент в психологии человека, что многие вещи, услышанные в течение жизни, начинают восприниматься как нечто само собой разумеющееся – вроде гравитации или магнетизма, хотя их кто-то в какой-то момент просто придумал.
В мозгу есть лайфхак на эту беду – «В пещерах такого не было», об этом я сегодня буду говорить с точки зрения IT.
Глава 0. База-1
Когда я учился в школе (199х) все пользовались Паскалем — язык понятный, мудрый, на нем был написан даже Dos Navigator с заставками VESA, а позже The Bat!, а участники олимпиады ACM ICPC в 2000-х были в основном паскалистами.Из-за моей любви к играм и графике я в то время столкнулся с C/C++, и мне сразу в глаза бросилась принципиальная разница — массивы индексируются с нуля или единицы, это еще надо уточнить на том же hackerrank.com. Все исходит из психологии человека, но не все пересматривается во времени.
С одной стороны, исторически в речи они нумеруются исходя из того, каким был предмет в момент добавления – отсюда «первый», «второй» – т. е.
сколько их было после добавления.
Но для компьютеров это неудобно, потому что.
Со смещениями оперировать проще - сколько байт нужно перепрыгнуть от базового адреса, столько "ноль", "первый".
Из-за этого конструкции Паскаля типа FOR I := 1 TO N DO A[I] := что-то излишне нагружают ALU или превращаются в квест для компилятора.
Есть еще один момент, где индексация 1.N дает о себе знать по сравнению с индексацией [0;N) — это работа с числами с плавающей запятой.
Если вам нужно собрать несколько отрезков впритык аля [а0;а1) U [а1;а2) U [а2;а3) – не существует «магических чисел» вида а1+1, а2+1 – конец одного сегмента является началом следующего, и этот критерий работает как для целых, так и для вещественных чисел.
В обозначениях 1.N даже целые числа начинаются с плюс-минус единиц, а для реальных по идее вообще нет :) хотя в С++ есть лайфхак (int&)++floatVariable; или более рекомендуемый std::nextafter. Большинство ошибок отклонения на единицу и сопутствующих им переполнений буфера происходят именно из-за этого.
Глава 1. Маленькое-большое приключение
Поначалу в пещерах были палочки/вырубки, чтобы научиться считать и освоить элементарную арифметику.
Затем в Египте придумали концепцию ноль/ноль (возврат к истокам 0-индексации).
Потом были римские цифры - красивые/гламурные/винтажные, но деление, как я слышал, изучали на четвёртом курсе вузов.
После этого цивилизация перешла на порядковую систему передачи – она пришла с арабской стороны; десятичное, видимо, по числу пальцев.
Но вот в чем дело: пишут они почему-то справа налево (об этом ниже), а импортировали как есть, и с тех пор мы пишем цифры от самой старшей до самой младшей цифры, хоть глаза разбегаются слева направо.
При этом выполняем практически все действия от самого младшего к старшему – запоминаем ручное сложение и умножение «столбиком» в тетради, справа налево.
Единственная операция, требующая ориентации слева направо, — это сравнение (и деление, поскольку оно связано со сравнением), но даже там числа заранее выравниваются по правому краю, подразумевая ведущие нули слева.
Теперь, собственно, об ИТ.
Когда мы начали проектировать процессоры и программировать, в разводку транзисторов просочились непродуманные человеческие привычки — появился big-endian (самый старший бит в первых байтах).
Потом было много холиваров, говорящих, что это, мол, дело привычки и не имеет значения.
Это играет роль — в случае с прямым порядком байтов смещение байта соответствует степени 256, которой оно соответствует. Как человек, познакомившийся с ассемблером x86 на 8086 в ~10 лет, я до сих пор помню такие вещи, как BL/BH/BX (позже EBX, еще позже RBX) - и когда нужно привести 32-битное int в 8 -бит, ALU вообще не требуется - это чисто вопрос интерпретации, базовый адрес остается прежним.
Поэтому и работает такое понятие, как «кармическое возмездие» — Motorola, PowerPC и SPARC остались только в банковском секторе, они улетели с нормального рынка даже после выхода на консоли XBOX/PS. ARM тем временем пытается угодить обоим и тратит на это литографический бюджет — каким-то образом порядок байтов в ней переключается.
Отсюда у нас есть такие вещи, как htonl и ntohl (длина от хоста к сети/длина от сети к хосту).
Мотивировано все это тем, что в древности сисадминам было психологически легче читать дампы, но мотивация, честно говоря, странная - если вы уже перепрошили свой биологический нейрон из десятичной системы в шестнадцатеричную - для достижения полного дзен достаточно всего одного шага расширенной перепрошивки мозга в математически естественном порядке младший-> старший, по возрастанию обращения.
И холивары были на эту тему, а кто-то даже потешался над РФК с лилипутами Блефуску и рисовал всё сверху вниз.
Нюанс в том, что в компьютере оно не симметрично.
Речь идет не о левом/правом или верхе/низе, а о том, идет ли он в порядке возрастания или убывания адреса.
При выделении памяти мы оперируем адресом первого нулевого байта, а не последнего.
Когда мы тянем malloc/realloc, обратный отсчет начинается с начала.
Часто кэши работают как с упреждающим чтением, так и с отложенной записью, особенно на механических HDD — т.е.
упор делается на увеличение адреса; симметрии с уменьшением адреса нет. Давайте двигаться дальше.
Когда мы говорим об «одноразовых» 8/16/32/64-битных числах, то это в принципе действительно не так важно и выглядит как холивар.
Но есть и «длинная арифметика» из сотен цифр.
При сложении можно перейти к прямому порядку байтов на ADD/ADC (x86), рассматривая части длинного числа как 32/64-битные, т.е.
при сложении число обрабатывается по основанию 2^64, а при умножении чтобы не переполняться, вы можете трактовать длинное число как, например, base-2^8 - вопрос интерпретации - и для этого не требуется никаких трюков SIB для ротации каждых 4 байтов в ALU. В случае с прямым порядком байтов — добро пожаловать в ад.
Глава 2. XYZ
С давних времен люди не могли договориться о том, где лево, а где право – и в 2020 году об этом говорит весь город и классика жанра, особенно когда дело касается вождения.
У некоторых людей к рукам была привязана ложка/вилка, у других возникали другие ассоциации.
Откуда взялось лево/право на основной оси X — думаю, это пришло от письма.
Сразу оговорюсь, почему он не вертикальный — с японской каллиграфией на полу, особенно в пещерах, непрактично шевелиться.
Стены редко трогают, а пол покрыт «мамонтовыми шкурами».
Плюс «петицию», написанную вертикально как второстепенную ось, можно держать за один верхний край – второй конец будет оттягиваться под действием силы тяжести, а горизонтальная прокрутка при вертикальном написании потребует двух гвоздей в стену или двух рук при чтении.
жить.
Когда вы что-то пишете, важен контекст — важен «задний предел мозга», т.е.
Желательно просмотреть то, что вы только что набрали.
Представим себе стандартного питекантропа рядом с пергаментом или каменной стеной, и он правша.
Чтобы увидеть уже «набранный» текст и с учетом физиологии тела (правша), текст пишется слева направо и сверху вниз.
Вероятно, отсюда и возникла ось X слева направо.
Между тем, в параллельной реальности, очевидно, доминировали левши — отсюда и RTL BiDi (проблемы двунаправленного письма справа налево) и упомянутый выше порядок байтов.
Далее идет ось Y, вертикальная.
Рене Декарт, и, скорее всего, раньше.
Они могли направить его вверх, могли направить вниз.
Полагаю, что не наводили, чтобы лишний раз не думать об Осирисе :) Но при этом суперфизики и суперматематики со всего мира изобретают телевизор и.
ось Y есть направлен вниз - ЭLT развертка кинескопа идет сверху вниз, и до сих пор технологически HDMI попадает еще и в LCD. Я считаю, что пиксели первого кинескопа ЭLT были связаны с направлением письма.
Дальше 3D забава - идем по оси Z. У некоторых (DirectX) наводится от глаз.
У других (OpenGL) это на глаз.
У других (Maya/3D-Max/Blender) местами вертикально.
Это опять-таки связано с психологией.
Кто-то привык воспринимать геометрию со школьной/университетской доски - тогда Z логично идет в направлении от, а кто-то привык рисовать чертежи дома на столе - и тогда XY лежит ровно на столе, а Z вверху под столом.
люстра с комарами.
Я смеялся в тот момент, когда в DirectX (10-11) Z-Buffer толерантно переименовали в Depth-Buffer :) На тему, почему ось Z приходит из глаза (DirectX) или в глаз (ранний OpenGL, может и сейчас тоже).
Есть такое понятие, как правоориентированный или левоориентированный базис, чтобы на векторном произведении работало «правило буравчика» или «правило отвертки» — подкручиваешь первый вектор во втором — получаешь направление результата .
Правая резьба/левая резьба – это всё примерно одно и то же, под какой рукой физиологически удобнее.
Нюанс в том, что при установленных математических Х-вправо, Y-вверх, получается, что логическая Z-вдаль порождает левоориентированный базис, что и сделали в OpenGL, направляя Z внутрь глаза тупо для ради правоориентированного базиса, но математически криво, потому что .
вам придется работать с отрицательными числами.
Есть еще одна, более простая версия, почему XY иногда находится впереди, иногда ровно.
И почему Z попадает в бровь, потом в глаз?
И чем дальше, тем круче становится.
Люди не могли договориться, как писать векторы — в строку или в столбец.
В российском университете (ПетрГУ) меня учили на курсах.
Похоже, что в OpenGL ситуация такая же.
В DirectX в MSDN я встречаю построчную запись — и воспринимаю ее как непривычную, но более логичную.
По одной простой причине - если поток мозга работает слева направо (я правша), то каскад преобразований в случае линейного представления вектора выглядит так при игре и чтении, т.е.
VxM1xM2xM3 , а не в обратном порядке операторов M3(M2(M1(V))), а в HLSL мы получаем объявление ориентации матрицы, так что строка/столбец удобна для всех.
Дело каждого — это ничьё дело.
Вернемся к XY. Одно время, еще в школе, меня удивила постановка вопроса о синусе и косинусе.
В тимологическом смысле косинус – это нечто, сопряженное с синусом (косинусом).
Однако более «первичный» синус определяется как отношение противоположной стороны к гипотенузе, хотя обсуждаемый угол образует прилежащий — и он вроде бы ближе.
Непонятный «переворот», хотя и математически логичный, ведь sin(0)=0 и sin'(0)=1 (у косинуса худшие ТТХ).
Та же ситуация и с касательной и кокасательной; технически тангенс также можно определить как cos(x)/sin(x).
Тангенс просто имеет больше смысла с математической точки зрения.
А теперь, внимание, вопрос: Почему, когда начали рисовать «стандартный математический круг» в радианах, они поставили первичный «синус» на вторичный Ось Y, а вторичный «косинус» разместили на первичном X? (X является «первичным» по той простой причине, что когда мы, люди, обсуждаем что-то одномерное, мы делаем это горизонтально).
Вот тут-то и возникает «перелом мозга», что есть часовая стрелка, а есть еще и математическая.
Один начинается сверху, по центру, а второй сбоку, посередине.
Плюс направление приходится вращать в голове.
Плюс все эти режимы Culling в DirectX с CW/CCW (по часовой стрелке/против часовой стрелки) и т.д. и т.п.
Представим на минутку, что подменыша не было, т. е.
X0=X=синус, X1=Y=косинус.
грех(0)=0, потому что(0)=1. Штаны превращаются в.
элегантный по часовой стрелке.
Вместо классического наследия недостаточного рефакторинга, с которым нам приходится иметь дело.
Вероятно, поскольку sin(x) против Икс Мы привыкли рисовать по ординатам как функцию.
(.
продолжение следует.) P.S: Все эти «репризы эпистолярного жанра» не просто так.
Часто в жизни бывают моменты, когда ты что-то придумываешь, а тебя обрывают фразы типа «это так неудобно».
Начинаешь размышлять, включать режим отладки мозга, только чтобы прийти к выводу, что «неудобно == непривычно».
Отсюда и название статьи - полный сброс в пещеры, когда не было идей, чтобы понять, где идеи, а где настоящая физика мира.
Время от времени имеет смысл делать ретроспективу своей жизни и взглядов с разными входными данными.
Часто «неудобное» вдруг становится «комфортным», а необычное — привычным, или наоборот. Это основа рефакторинга.
Теги: #математика #программирование #история ИТ #рефакторинг #наследие #история #история #совместимость
-
Находите Файлы На Жестком Диске Быстрее
19 Oct, 24 -
Чередование Выборки В Mysql
19 Oct, 24 -
Семат? Рад Встрече
19 Oct, 24