Архитектура компьютера→Троичный язык программирования
Мнения
001 Основная сложность - троичная логика. В простой логике: 0 - ложь, 1 - истина. Здесь, наверно, -1 - ложь, 0 - неопределенно, 1 - истина
Кидайте свои идеи002 Речь идёт про абстрактный язык верхнего уровня? То есть про троичный язык программирования, на котором можно писать на существующих платформах?
003 В принципе вариантов может быть несколько:
1. Язык ассемблера для реальной троичной ЭВМ, если она в принципе существует (насколько я знаю, сейчас их созданием особо не занимаются - Сетунь не в счет!!!)
2. Интерпретатор для двоичной ЭВМ (по типу интерпретатора языка Python)
Не это главное. Хотелось бы поразбираться в интересными вещами:
1. реализовать троичную логику (как это будет выглядеть в циклах, условных операторах и т. п.)
2. определиться с обозначениями состояний трита (по типу 0 и 1 у бита)
2. поэкспериментировать с тритами и трайтами
3. На основе количества возможных состояний трайта придумать кодовую таблицу символов
4. организовать эффективный перевод из десятичной системы в уравновешенную троичную и обратно
Мои предложения:
1. жду ваших идей
2.
-1 false (только "минус" писать над единицей)
0 undefined (null)
1 true
(в варианте Сетуни [- 0 +] мы запутаемся с операциями сложения и вычитания, NOP и NZP для непосвященных непонятно, [0,1,2] - логично, но для обычной троичной системы, а у нас уравновешенная троичная) подробнее см. раздел "Ближе к делу"
3. Таблицу символов обсудим все вместе. Сначала главное оценить ее размер. Будем мучаться с кодировкой, как это было с таблицей ASCII или сразу сделаем UNICODE
4. Насчет перевода: кто нибудь знает простой или эффективный алгоритм (лучше одновременно и простой и эффективный). Прошу учесть суть задачи:
строку с символами диапазона [0-9] преобразовать в тритовое представление и обратно, используя только операции сравнения, чтения и записи ячеек памяти004 1. if (a) action_a-; action_a0; action_a+;
2. Я всё таки, пока что, склоняюсь к [-, 0, +], а операции сложения можно для примера по особому обозначать, например (+), (-), то есть как знаки в кружке :)
Для 9-ричной записи также уже давно был предложен вариант [z, y, x, w, 0, 1, 2, 3, 4].
3. Несомнено что нужно ориентироваться на UTF-8, однако пока нет однозначно договорённости на размер трайта, который бывает как 6 тритный и 9.
4. Возможно, что эффективный алгоритм получится, если последовательно преобразовывать троичную в девятиричную, из которой уже в десятичную.
166 Идея такова:
There is only three types of yoga: monism (0), dvaita (-+), advaita(-0+).
-0+
ложь холизм истина
Некоторые примеры холизмов: мир0 (world0), холистическая клетка, холистическая сфера, объект (object), субьект, ultimate freedom, exception, холистическое топологическое (т.е. непрерывное или аналитичное) множество, холистическое синергетическое (т.е. разрывное) множество, далее сущности графово-нестандартного анализа и графово-нестандартно-категориального анализа, а также хаос и даже лукавый ответ или речь и сатана (как примеры физических мистически-субъективных восприятий многих людей, выражаемых многими физическими строками букв на бумаге и экранах). Не вполне строго: множества могут быть открытыми или замкнутыми, etc.
Обычная (бинарная) математическая логика холизмы отрицает в силу общепринятого в ней закона исключённого третьего, т.е. закона исключенного сатаны.
P.S. Просьба не удалять, потому что опровергнуть сии тысячелетиями известные вещи невозможно, это не "бред," а вполне малоизвестные свидетельства; флудить или добавлять я что-либо не собираюсь --- желающие сами изучат. И тернарная информатика и тернарная математика (которую я уже давно изучаю) открывает к ним метод. Однако на хорошие вопросы отвечать готов (предельно сдержанно).
P.P.S. Я пару лет занимался практикой в одном адвайтинском течении йоги, и притом я математик (не закончил вуз (НГУ), ушёл). Особенно любил мат.логику.167 Это сообщение выше, в основном, поясняет сложности условного оператора.
168 Ах да, ещё забыл проективные связи чего угодно с чем угодно (cf. ultimate freedom). И особенно мультимодельность и проективные модели, но это на сладкое.
169 Не забудьте про примитив inplace subst 0:=0, где нули разные. Он может журналироваться.
170 Как это вообще соотносится с троичкой?
Данный проект, как и форум, не занмается "мистически-субъективными восприятиями",
поэтому P.S., к сожалению, не возможно удволитворить.172 Ну научную книгу по вопросу мне писать лень, так что поступайте как знаете.
173 К троичной логике имеет самое наипрямейшее отношение. Если вы не улавливаете, то просто неумны. Так что если так, то удаляйте всё смело, на этом ресурсе все мои постинги и моего пользователя и всё прочее моё можете стереть, знать вас не хочу (если так).
171 Это вообще достаточно распространенное заболевание.
174 Да, глупость нередка.
175 Фильм "Игры разума" наглядно показал, что прописанные лекарства надо принимать строго по часам, без пропусков. Тогда не будет визитеров, неожиданных ассоциаций и толп глупых людей вокруг.
176 Я вот чрезвычайно глубоко сомневаюсь, что в метре от вас лежит т.1 Чёрча. Будете тут меня идиотической голливудской попсой ещё кормить, доктор без квалификации.
005 Впредь предлагаю обсуждать такие вопросы:
1. Реализация троичной логики в условных операторах
2. Обозначения состояний трита
3. Логический тип данных
4. Количество трит в трайте
5. Кодовая таблица (тесно связан с вопросом 4)
6. Алгоритм переода из десятичной системы в уравновешенную троичную и обратно)
Мои предложения:
1. Насколько я разбираюсь в теории программирования, операции if - else, циклы while и for, переключатель switch и прочие ветвления и циклы можно перевести к оператору условного перехода goto: if условие goto адрес_перехода. Если еще проще, то в двоичной ЭВМ это сводится к двум развовидностям оператора:
if a==1 goto адрес
if a==0 goto адрес,
где a - логическая переменная (результат выполнения сравнения).
Пример:
bool k=(a>b);
if k==1 goto metka1;
if k==0 goto metka2;
В троичной логике:
if k==0 goto met1;
if k==+ goto met2;
if k==- goto met3;
(В Сетуни используется этот вариант: команды: 0+0, 0++, 0+-)
2. В принципе обозначать можно как угодно. Я знаю такие распространенные варианты:
1) -0+
2) NOP
3) NZP
4) -1 0 1
Голосование по этому поводу проводить рано, сначала надо рассмотреть аргументы. У меня такие:
1) -0+ вроде интуитивно понятно, но зачем придумывать (+) и (-) для обозначения сложения и вычитания, когда несколько веков используют просто + и - (к тому же () - это операторные скобки)
2) NOP и 3) NZP дополнительно надо объяснять, о чем идет речь
-
4) 1 0 1 основная сложность, что в таблице символов ASCII нет сомвола для -1 (насчет UNICODE не знаю), поэтому такая нотация сложна для обсуждения.
Это насчет состояний трита.
3. Другой вопрос - логический тип данных. Конечно, можно его не вводить (как не было его, например, в языке C), а пользоваться обозначениями состояний трита, но я предлагаю все-таки ввести: тип boolean (или bool, BOOL, кому как нравится). Диапазон значений:
1) false
2) null (undefined)
3) true
С другой стороны возникает вопрос о "таблице истинности" с трехмерной логикой. В теории реляционных баз данных используется такая таблица
A B not A A and B A or B a==B
1. false false true false false true
2. true false true false true false
3. true true false true true true
4. true null null null true null
5. false null null false null null
6. null null null null null null
4. В принципе, количество трит в трайте может быть любым (в байте не всегда было 8 бит, когда-то их было 7 или 6). По этому поводу в Википедии есть очень интересная заметка (http://ru.wikipedia.org/wiki/Трайт). Я предлагаю рассматривать следующие варианты, как наиболее логичные:
1) 1 трайт=1 три (и дальше не париться)
2) 1 трайт= 3 трит (первое число, являющееся степенью тройки)
3) 1 трайт= 6 трит (как в ЭВМ Сетунь)
4) 1 трайт= 9 трит (3^2, по аналогии 1 байт= 8 бит (2^3))
5) 1 трайт=27 трит(наиболее логичный вариант, так как 27=3^3, но слишком громоздко)
5. Идея utf-8 хороша, но ее придумали для обратной совместимости с ASCII, а у нас обратно совмещать не с чем, поэтому все-таки удобно, когда любой символ кодируется одинаковым количеством трайт (трит). Это упрощает многие алгоритмы (представить алгоритм поиска симола в строке с кодировкой utf-8). Я предлагаю рассмотреть такие варианты:
1) 1 трайт=6 трит (3^6=729 - явно мало, если использовать два трайта, то 3^12=531441, что достаточно (на настоящее время))
2) 1 трайт=9 трит (3^9=19683 - уже больше, но не годится для аналогии с 2^16=65536, а два трайта - 3^18=3*10^8 (скорость света!!!) хватит до скончания веков - IMHO)
3) 1 трайт=27 трит - тут хватит еще больше, чем до скончания веков
6. Я предлагаю такой алгоритм: десятичное число представляется ввиде линейной комбинации: 349=3*10^2+4*10^1+9*10^0. Далее преобразование проводится для каждого разряда в отдельности (этих вариантов не много и их можно хранить в памяти), а результаты складываются:
349=3*10^2+4*10^1+9*10^0=++-0+0(+)++++(+)+00=+++0-+ (как неудобно использовать (+) :-)006 1. Вместо goto лучше использовать блоки {}
Тут основной вопрос как интертерировать логические выражение, одно дело когда производим числовые сравнения, так 3 ветви вполне очевидны. А как быть с логическими ветвлениями?
В Сетуни анализировался именно знак а не логические выражения.
Хотя если говорить о том, что логические выражения возвращают true, false и null, то тут также очевидны три ветви.
Например
iffalse (true && null) {
} ifnull {
//выполнится эта ветвь
} else {
}007 2. Так и не ясно, к какому решению склоняетесь.
Независимое голосование показало что для людей наиболее очевидными обозначениями являются [+,-,0].
Также надо заметить, что на данный момент в обиходе 0,1 практически не используется. Числа записывают либо в десятичной системе, либо в шестнадцатеричной. Так и здесь возможно наиболее употребительным может стать запись в девятеричной системе, например символами [z, y, x, w, 0, 1, 2, 3, 4]. Где же требуется поразрядная запись использовать [+,-,0].008 3. вроде как должна быть таблица три на три, ссылочку на источник можно?
Первое что пришло в голову:
[+] [0] [-]
----------------
[+]|[+] [0] [-]
[0]|[0] [0] [0]
[-]| [-] [0] [+]
То есть таблица умножения :)009 4. Ну и какой же выбор?
2,4,6,8.. трит можно представить 1,2,3,4 символами в девятеричной системе. Собственно поэтому то 6 трит и девятеричная система фигурировала в Сетуни.010 UTF-8 действительно хороша: гибкая, в меру экономная, и расширяема. Создана она была не из-за совместимости с ASCII, а для разрешения вопросов с расширяемостью алфавита, ИМХО.
Таким образом тут запросто подойдёт и 6-тритный трайт.
Да есть заморочки с точки зрения работы с такой системой как UTF-8, но они решаемы, таким образом можно получить одни плюсы.
Что касается 9 и 27 трит на символ,
допустим 27 трит — 7625597484987 значений. Только вот как часто будет использоваться символы с конца диапазона?
Английский наряду с китайским занимают 40% языков мира,
То есть в каждом пятом случае используется английский язык, который как раз-то и умещается в 1 байт. С другой стороны китайский язык, в котором примерно 8000 употребительных иероглифов, а всего их более 80000. То есть, для того чтобы уместить их требуется минимум 11 трит (3^11 = 177147). Однако вероятность их употребления очень низка. Из всего этого следует, что использовать для кодирования символов традиционный подход из фиксированного количества трит для всех языков — сомнительно.011 6. Алгоритм интересный, однако не ясно что значить "хранить значения преобразований в памяти", и почему их немного.
Т.е. хранить в памяти троичные значения всех возможных вариантов: [0-9], [100, 200, 300, 400 ... 900], [1000, 2000, ... 9000] и т.д. В принципе действительно интересно, однако на каком порядке нужно остановиться?
Из плюсов, несомненно — это скорость и простота. Минус пока вижу только в ограниченности диапазона преобразований.016 6. По моим прикидкам чтобы поддерживать 64 бита, т.е 2^64 десятичные числа, это 20 десятичных разрядов, требуется 42 троичных разряда. Таким образом получается 8400 трит, что в принципе также остаётся допустим.
В связи с этим есть ещё один вопрос, на какой платформе идёт осуществление перевода из десятичной в троичную симметричную? Ведь как на двоичной, так и на троичной платформах, десятичные числа уже каким то образом должны быть представлены.
012 1. Я имел в виду язык ассемблера (или машинный код), где инструкции записаны по порядку и нельзя создавать блоки {} (весь ко дна одном уровне):
149D:0100 MOV AH,02
149D:0102 MOV DL,41
149D:0104 MOV CX,001A
149D:0107 INT 21
149D:0109 INC DL
149D:010B LOOP 0107
149D:010D INT 20
149D:010F.
Единственный способ организовать условный переход в такой ситуации - использовать оператор goto (или иму подобные). В приведенном примере замыкается цикл оператором loop.
В нормальных языках программирования, где в принципе возможно неограниченное число вложенных структур, конечно, удобно использовать for, while, if, switch и прочие прелести языков высокого уровня. Я имел в виду, что любая конструкция при компиляции в машинный код сводится к некоему подобию оператора goto (я почти ничего не понимаю в языке ассемблера, поэтому знатоки могут меня поправить).
На мой взгляд при реализации двоичной логики в программировании превалирует идея: условие выполняется или нет (третьего не дано). У нас есть возможность добавить другие возможности. Например:
1) если у объектов есть понятие "больше", "меньше", "равно" (как например у чисел), то можно ввести оператор compare(x,y), который возвращает одно из этих трех
2) логический оператор может возвращать false, Null, true
2. Второй вопрос, насколько я понимаю, вы предлагаете похоронить. В принципе, если нет необходимости в поразрядной записи, то какая разница, как ее обозначать. Единственный пример, который мне приходит в голову, это расчет сетевых адресов в стеке протоколов TCP/IP (протокол IPv4: 142.123.56.2), но это уже не проблема, так как в IPv6 будут переходить к шестнадцатеричной записи.
3. Если обозначать состояния трита можно как угодно (- 0 +, NOP, NZP, -1 0 1), то для логического типа данных нужно выбрать обозначения. То, что (-1) - false, а 1 - true, ИМХО, можно не дискутировать. Для нуля есть несколько вариантов:
1) null (можно спутать с нулевым указателем NULL в C++)
2) nil (в языке LISP обозначает ложь, поэтому не логично)
3) None (неопределенное значение например в Python)
4) undefined (слишком длинно писать)
5) nothing (ИМО, это в Visual Basic что-то типа проверки на пустоту)
6) empty (это мне совсем не нравится)
Я все-таки склоняюсь к варианту null, который давно используется в реляционных БД (и обозначает именно - неопределенное)
Таблицу истинности я списал из тетрадки по базам данных, поэтому ссылку дать не могу. Наберите в Google "таблица истинности null" и узнаете много интересного. Любопытно было почитать "http://articles.org.ru/docum/sql_oper.php" и "http://www.interface.ru/home.asp?artId=2407"
4. По определению:
Трит - минимальная единица информации
Трайт - минимальная адресуемая ячейка памяти
Исторически сложилось, что 1 байт=8 бит. ИМХО, это возникло в пору, когда в ходу было 8-разрядные процессоры. Когда потом появились 16-разрядные, то было написано уже много кода, ориентированного на то, что 1 байт=8 бит, и решили так и оставить. Поэтому и сейчас на 64-разрядных процессорах 1 байт=8 бит, хотя эффективность в этом случае слегка ниже, чем если бы было 1 байт=64 бит. Процессору выгоднее обрабатывать 64-разрядные слова, чем дробить их на 8-разрядные.
По этой же причине логический тип данных сделан размером в 1 байт, а не в 1 бит, хотя это и сэкономило бы много памяти, но разбирать 1 байт по битам невыгодно с точки зрения быстродействия. Вообще, сейчас для 90% пользователей на первый план выходит быстродействие, а не память, которая при этом теряется (благо современные технологии это позволяют). ИМХО
Я думаю, что размер трайта должен эффективно подстроиться под кодовую таблицу символов, которую мы, надеюсь, придумаем
5. Посмотрел ваши цифры и понял, что сколько трит (или бит) под кодовую таблицу не оставляй, все равно рано или поздно не хватит, поэтому идея utf-8 выглядит неплохо. С этой точки зрения 6-тритового трайта должно хватить для кодировки основных символов (отсюда логично название UTF-6). В оригинальном UTF-8 какая-то замудренная логика, по которой определяется, сколько байт отведено под символ, если он не из ASCII. Надо придумать что-то попроще. Так же необходимо указать максимальное количество трайт, приходящихся на один символ.
Другой вариант (для наглядности взял 1 трайт=6 трит): в первом трайте у нас 3^6=729 комбинаций. Допустим, чтобы закодировать основные символы (назовем их также - ASCII) у нас ушло 5 трит (3^5=243) и 1 остался (пусть он будет первый). Для ASCII он равен 0. Если первый трит не ноль (-1 или +1), то значит символ не из ASCII и в последующих 5 тритах вместо кода ASCII записывается натуральное число - сколькими трайтами закодирован данный символ. То есть в принципе можно использовать 3^5=243 трайт, что позволяет закодировать (3^6)^243=4*10^695 символов. Можно хоть смайлики кодировать. Нужно только правильно выбрать коды для символов: основные (ASCII) у нас кодируются 1 трайтом, часто употребляемые 2-4 трайтами, далее остальные. ИМХО, получилось что-то похожее на дерево Хаффмана (скорее не по структуре, а по идее).
Отсюда у меня возникает предложение (знатоки языков C/C++ меня поймут): надо отделить строковый тип данных и тип данных, предназначенный для побитового (у нас потритового) представления объекта (в C++ - это char). Для символа нужно создать тип char, а для потритового представления тип - tryte (я надеюсь, я правильно написал "трайт" по-английски, а "трит" пишется "trit" ИМО). Ни программист, ни пользователь не должны подозревать, сколькими трайтами закодирован данный литерал. Если пользователь еще переживет, то программисту нужно "образать" возможность что-нибудь оптимизировать для типа char. Все операции для типа char должны быть "вшиты" в язык (инкапсулированы от пользователя и программиста).
По этому вопросу можно открыть отдельную тему, если кому интересно.
6. Ваш вопрос - на каком порядке остановиться. Возьмем для примера язык C++. Для 32-разрядного процессора (4 байта) наибольшее целое число 2^32=4 294 967 296, то есть можно остановиться на 10-ом порядке десятичного числа, то есть имеем 100 вариантов (по 10 для каждого разряда), то есть понадобится 4*100=400 байт. Если учесть, что эту операцию нужно проводить довольно часто, 400 байт памяти не жалко. Для 64-разрядного числа нужно 800 байт. ИМО, для троичной системы исчисления цифры сильно не поменяются.
Одна проблема: как с помощью этого алгоритма преобразовать число братно в десятичную систему из уравновешенной троичной.013 Со своей стороны позволю себе сделать небольшое замечание по поводу синтаксиса команд ассемблера. Я не понимаю почему нельзя записывать команды не сокращениями слова, а соответствующими операторами:
- пересылка «?»
- сложение «+»
- вычитание «-»
- деление «/» или «?»
- умножение «*» или «?»
- сдвиг «>» и «<»
- равенство «=»
- неравенства «?», «?» и «?»
и так далее.014 К сожалению не все символы отобразились верно, поэтому заменю их на другие:
- пересылка «->»
- сложение «+»
- вычитание «-»
- деление «/»
- умножение «*»
- сдвиг «>>» и «<<»
- равенство «=»
- неравенства «!=», «>=», «<=»018 Решил прилодить набор символов в виде изображения.
019 По моему первоначальный вариант более функциональный, потому как иначе придётся программистам настраивать типографическую раскладку )
020 Под первоначальным подразумевается вариант из простых символов, таких как -> и т.д.
021 Это не обязательно, среда разработки вполне может самостоятельно определить контекст и подставить необходимый символ. Мне очень удивляет почему этого до сих пор не сделали. Это очень похоже на «графический планшет» по которому водят гусиным пером, смачивая его специальными проводящими чернилами.
022 В таком контексте вполне уместно
015 Предлагаю обсуждать кодирование символов в отдельной ветке:
http://trinary.ru/forum/view/5/20017 Thunguska the ternary computer emulator
http://www.acc.umu.se/~achtt315/tunguska/
По сообщению разработчика разрабатываются: троичный ассемблер, троичный компилятор с С, троичная операционная система. Желающим предлагается скачивать текущие версии.023 Так как в троичной логике двоичная логика является центральным подмножеством, то нет необходимости разрабатывать полностью новый транслятор (компилятор), т.к. это очень трудоёмко и неизвестно чем кончится. Нужно взять трансляторы широко используемых языков программирования, к которым привыкли программисты, прошедших проверку временем, с открытым кодом и дополнить их операторами троичной логики. Это менее трудоёмко и сохраняет полную совместимость с предыдущим двоичным программным обеспечением.
024 А что вы думаете про язык для этой платформы:
http://www.acc.umu.se/~achtt315/tunguska/
?033 Троичная логика, конечно, является подмножеством двоичной, и трит может эмулировать бит, но мне с трудом представляется хранение чисел и операции с ними на тритах, если они эмулируют биты (да смысл троичной системы и все ее преимущества теряются)
Можно создать транслятор похожий на обычные языки (так и стоит делать и не изобретать велосипед), но полная совместимость невозможна. Создавать придется, конечно не с нуля, но создать новый троичный транслятор методом "добавить недостающие функции" не получится
037 1. Для начала советую обратить внимание на реляционный язык SQL, где применяется троичная логика.
2. Поддерживаю булевский тип BOOLEAN (FALSE, NULL, TRUE) = (-1, 0, 1), как вариант (FALSE, UNDEF, TRUE) (UNDEF мне нравится больше, так как выражает сущность - неизвестно). Кстати, можно на 7 сегментных индикаторах вместо -1 выводить F, а чтобы не путать её с шестнадцатиричной системой, развернуть на 180 градусов. Получится уникальный символ :).
3. Базовую конструкцию IF использовать следующим образом (стиль оберона):
IF <condition> {CORRECT <true>} {UNKNOWN <undef>} {WRONG <false>} END;
Таким образом возможны следующие варианты:
1. IF (a > 5) CORRECT proc1 END;
2. IF (a > 5) UNKNOWN proc1 END;
3. IF (a > 5) WRONG proc1 END;
4. IF (a > 5) CORRECT proc1 WRONG proc2 END;
5. IF (a > 5) CORRECT proc1 UNKNOWN proc2 END;
6. IF (a > 5) UNKNOWN proc1 WRONG proc2 END;
7. IF (a > 5) CORRECT proc1 UNKNOWN proc2 WRONG proc3 END;
4. Однозначно определить циклы (стиль оберона) WHILE <condition> DO <body> END; и DO <body> WHILE <condition> END как циклы исполняющиеся пока <condition> = TRUE;
и циклы (стиль оберона) REPEAT <body> UNTIL <condition> END; и UNTIL <condition> REPEAT <body> END; как циклы исполняющиеся пока <condition> # TRUE, т.е. = FALSE или UNDEF.038 Ваши мысли весьма верны, но смущает одно: почему всё не по-русски? Ведь именно мы, русские, создали первую и единственную троичную ЭВМ. Надо нам же создать и троичный ЯП, тоже русский.
039 Поставьте себе 1С и вперёд, наслаждаться русским.
040 Такая идея была давно, тем более что если отбросить Ё и использовать 32 оставшиеся буквы, то получим 32-ричную систему :)
В принципе можно попробовать типа:
ЕСЛИ (<условие>) ВЫПОЛНЯЕТСЯ <что-то> НЕИЗВЕСТНО <что-то> ОШИБОЧНО <что-то> ВСЁ
конечно занимательно, но это может существенно отпугнуть программистов при переходе на троичный язык.041 Не только "может отпугнуть" но совершенно точно отпугнёт всех, кто не владеет русским языком.
048 Насчёт Ё - не слышал, лишь совсем ущербные кодировки её не имели (было даже, что твёрдый знак не имели), но мы-то обсуждаем троичную машину, значит и кодировка троичная должна быть. Русский язык использует 38 букв и апостроф (тоже по сути буква), из них 33 — великорусский алфавит, ещё 3 буквы — для дореформенной орфографии. Таким образом, под русские буквы в кодировке должно быть выделено не меньше 83 мест. Плюс к тому — специфические символы русской типографики (например, два вида кавычек). Уникод троичный тоже придётся делать. Но речь сейчас не про кодировки.
Русские языки программования — это не просто идея. Русские ЯП использовались раньше, в советское время (вспомните, например, Рапиру, КуМир, несколько учебных языков, типа Робика или Алгоритмического, русские ассемблеры для наших машин (в т.ч. для БЭСМ-6) и прочее), и используются даже сейчас, например, язык Глагол, русский аналог Оберона. Насчёт отпугивания: если программистов не отпугнёт троичная логика, то к русским служебным словам они запросто привыкнут.
042 Ребята, о чем спорим!
Можно писать синтаксические конструкции хоть на 20 языках сразу. Проблема решаема по крайней мере 2 способами:
1. Посмотрите язык 1С
2. Можно выбрать один основной язык для компилятора и перед компиляцией автоматически переводить все синтаксические конструкции на него044 Каким образом вы собираетесь обмениваться фрагментами исходного кода с иностранцами ?
045 Нужно создать взаимнооднозначное соответствие между синтаксическими конструкциями на разных языках и использовать автоперевод
046 Именно, по примеру языка 1С. Но, в отличие от последнего, нерусские служебные слова надо будет добавить лишь после того, как в этом будет реальная нужда, то есть когда троичный ЯП станут использовать и иностранцы, о которых мы должны думать в последнюю очередь.
047 Ну, наверно, не в последнюю. Основа международного успеха продукта - встроенная возможность к локализации продукта
049 Сильно ли об этом заботятся современные разработчики ЯП? Их логика проста и понятна: зачем переводить служебные слова, если программист их может просто выучить, и это, якобы, упростит совместную работу программистов из разных стран? На самом деле, это лишь создаёт препятствия к изучению этих языков и сокращает скорость работы программиста, а проблема международной разработки решается очень просто, как Вы верно заметили.
Прежде всего для нас должен быть важен успех новых разработок в России. Если мы сможем производить эффективные троичные ЭВМ и писать качественные троичные программы, то что нам будет мешать пользоваться логикой упомянутых выше разработчиков, но с использованием русского языка?051 Я согласен, что в первую очередь мы должны заботится о том, чтобы:
1. Было удобно программисту (пользователю по барабану на каком языке велась разработка).
2. Конструкции языка были компактные, логичные и хорошо передавали смысл того, для чего они предназначены.
Если для этого подходит русский язык, то нужно использовать русский язык.
043 Итак, возникла проблема с оператором IF (ЕСЛИ). А все из-за того, что мы имеем 3 состояния логической переменной, а не 2. Логика работы оператора IF заключается в том, что машина может однозначно вычислить условие ("Да" или "Нет"). Все, что "Да" выполняется, а "Нет" отсылается оператору ELSE. Получается, что проблема именно в операторе ELSE, потому что в двоичной логике под словом ИНАЧЕ понимается нечто определенное (противоположное ЕСЛИ). В троичной же логике понятие ИНАЧЕ неоднозначно: для условия ПЕРЕМЕННАЯ1==ПЕРЕМЕННАЯ2 понятие ИНАЧЕ включает в себя не только ЛОЖЬ, но и НЕОПРЕДЕЛЕННО.
Поэтому в самом простом случае оператор IF имеет право на существование, но только без блока ELSE. Например, конструкции
если (k==0) блок1;
иначе блок2;
и
если (k!=0) блок2;
иначе блок1;
эквивалентны только в двоичной логике.
Если надо обработать 3 варианта (-1 0 1) или же 2 варианта (-1 1), то для этого существует прекрасная конструкция:
(для С)
switch(a)
{
case -1: блок1;
case 0: блок2;
case 1: блок3;
}
(для С)
switch(a)
{
case -1: блок1;
case 0: блок2;
case 1: блок3;
}
(для С)
switch(a)
{
case -1: блок1;
case 0: блок2;
case 1: блок3;
}
(для VB)
select a
case -1: блок1;
case 0: блок2;
case 1: блок3;
end seelct
(если я правильно аомню синтаксис)
Вообще, оператор ЕСЛИ предполагает работу с логическим значением, а не с выражением, поэтому хорошим тоном было бы вместо конструкции
ЕСЛИ пер1==пер2 ТОГДА что-то
использовать
лог_знач=(пер1==пер2)
ЕСЛИ лог_знач ТОГДА что-то
Если в двоичных языках это не слишком заметно, то в троичном часто полезно делать так, особенно для программиста, которому легче понять: "А какое условие я собственно хочу проверить?"
IMHO. Это же касается всех конструкций, где проводится проверка условия (например, условия выхода из циклов).
Итак, мое предложение:
1. Использовать оператор IF, но только без конструкции ELSE. Сделать 3 разновидности оператора: IF_TRUE, IF_FALSE, IF_NULL (IF как синоним IF_TRUE)
2. Для проверки двух или трех вариантов использовать конструкцию SELECT...CASE (она же SWITCH...CASE)
3. По аналогии для циклов писать WHILE_TRUE, WHILE_FALSE, WHILE_NULL
Пример
do
{
k=input("Вас устраивает ваша зарплата")
switch(k):
{
case false: print("Сожалеем")
case null: print("Определяйтесь!")
case true: print("Вы - счастливый человек")
}
}
while_null(k);050 А чем вам не понравилось моё предложение?
использовать троичный IF и циклы, или вообще цикл Дейкстры.
Троичный IF:
if (<condition>) then { ... } undef { ... } wrong { ... } else { ... }
Если условие верное, то выполняется всё, что стоит после "then", если условие не верное, то выполняется всё что стоит после "wrong", и если условие не определено, то выполняется всё что стоит после "undef".
Кроме того, IF можно использовать следующим образом:
если условие (выполняется/не выполняется/неопределено), то выполняется тело, которое стоит после (then/wrong/undef), а далее следует ключевое слово else, после которого операторы, которые выполняются в остальных случаях. Например:
if (a > 5) then { b = a } else { b = -a }
Если условие выполнено, то b будет равно a, если условие не выполнено или неопределено, то b будет равно -a.
Аналогично и для ситуаций
if (a > 5) wrong { b = a } else { b = -a }
if (a > 5) undef { b = a } else { b = -a }
по циклам:
ЦИКЛ WHILE
while (<условие>) do { ... };
do { ... } while (<условие>);
цикл выполняется пока условие верное (+1)
ЦИКЛ REPEAT
repeat { ... } until (<условие>);
until (<условие>) repeat { ... };
цикл выполняется пока условие не верное
ЦИКЛ Дейксты
do {
if (<condition>) correct { ... };
...
if (<condition>) correct { ... };
} do
Тело цикло может содержать только операторы IF только с условием CORRECT. Цикл завершается, если ни одно из условий не выполняется (не сработал ни один оператор из тела IF).052 Я вам особо не противоречю. Ваша конструкция
IF <condition> {CORRECT <true>} {UNKNOWN <undef>} {WRONG <false>} END;
это тот же Select...Case только другими словами.
Я просто предлагаю не довешивать в классическую структуру оператора IF... ELSE дополнительные слова. 3 варианта троичной логической переменной можно обработать в операторе Select...Case.
А если через несколько лет будем создавать 5-ричные ЭВМ, тогда IF будет выглядеть страшно:
ЕСЛИ <условие>
{НЕВЕРНО блок1}
{ПОЧТИ_НЕВЕРНО блок2}
{НЕОПРЕДЕЛЕННО блок3}
{ПОЧТИ_ВЕРНО блок4}
{ВЕРНО блок5}
КОНЕЦЕСЛИ;
В двоичных языках цикл IF широко используется для проверки 2 состояний логической переменной.
Проверка на истинность:
ЕСЛИ пер1: ......
Проверка на ложь
ЕСЛИ НЕ пер1: ......
В троичном языке проверка на ложь по типу "ЕСЛИ НЕ пер1: ......" не пройдет, не говоря уже о том, что если пер1 равна НЕОПРЕДЕЛЕННО, то "пер1" и "НЕ пер1" вернут одно и тоже (а именно, НЕОПРЕДЕЛЕННО)
Я предлагаю использовать оператор IF только для проверки логической переменной на соответствие одному конкретному состоянию (ИСТИНА, ЛОЖЬ, НЕОПРЕДЕЛЕННО)053 Вы говорите о преобразовании старых языков, а я предлагаю создать совершенно новый.
А до 5 мерных компьютеров не дойдёт, ибо ПИ (3.1415926...) и никуда от него не деться, а 3 самое к нему близкое...054 А причём тут число Пи?
056 Просто есть одна теория (не моя), которая находит достаточно много подтверждений, что наш мир не трёхмерен, а ПИмерен :)
Соответственно, базис 3, ближе к базису нашего мира, чем какой либо другой.058 Размерность по определению может быть лишь натуральным числом (включая 0). Впрочем, я толком не знаю, что эта теория имеет ввиду, ибо не читал её. Но вопрос возникает другой: какое отношение размерность пространства имеет к логике, использущейся в цифровых ЭВМ?
070 Размерность может путь любым числом (математически), по крайней мере рациональным. Мне это говорили по крайней мере 2 человека: оба кандидаты физ-мат наук
079 Ну допустим, что теория верна и наше пространство пи-мерно. Так какое-же отношение эта размерность имеет к вычислительной технике?
080 Я не говорил, что размерность имеет отношение к вычислительной технике, а привел пример, что если размерность логики более 2, то оператор if становится жутко некрасивым.
Кстати, ниже мои комментарии относительно логических операторов в троичном языке
055 Мне кажется вы спутали число ПИ и основание натурального логарифма e.
057 Не спутал (см. выше), хотя и e и Пи, оба близки к 3. Так что вариантов с 5-мерной системой, равно как и с другими - не предвидиться
069 Кстати, любопытные примеры.
1. Если цикл DO WHILE(<условие>) будет выполняться пока условие верно, то мы не сможем выполнять проверку на неопределенность. Доказательство:
bool k;
do
{
k=input("Введите null для продолжения цикла");
}
while(k==null);
Этот цикл не имеет продолжения, так как условие (k==null) при любом k вернет null, а для продолжения цикла надо true
2. Рассмотрим оператор IF
k=input("Введите null, чтобы выйти из программы");
if (k==null)
{
exit();
}
Пользователь не сможет выйти из программы, так как опять же проверка условия (k==null) всегда возвращает null, а не true, которое надо для входа в блок if
Поэтому для операторов IF и WHILE я предлагаю конструкции типа IF_TRUE, IF_FALSE, IF_NULL, WHILE_TRUE, WHILE_FALSE, WHILE_NULL, которые будут не СРАВНИВАТЬ значения, а проверять СООТВЕТСТВИЕ переменной значению.
Мы привыкли, что a==a всегда верно, но для троичной логики это не работает: проверка на равенство с null всегда дает null, даже проверка (null==null) дает не true, а null. Задайтесь вопросом: "Что будет, если сравнить неизвестное с неизвестным?". Мой ответ: "Неизвестно".
В связи с вышеизложенным предлагаю пока оставить тему операторов IF и WHILE в покое: определимся с троичной логикой (см. ниже)
157 maybe "TRILEAN" or "TRIL" better? Also "TrIF" instead "IF":
TrIF #&(tnul , ==(trInteger X, trInteger Y)
case ~1 proctrNEG
case +1 proctrPOS
case tnul procUNestimated
endTrIF
059 Прошу высказать мнения насчет справедливости следующих таблиц истинности
060 отрицание
061 Умножение
062 Сложение
063 Сложение
066 У меня сомнение только имена колонок вызвали: A or B,+ ИЛИ - результат 0, то есть условие ИЛИ не выполнилось.
064 Честно говоря, во многом я сам не уверен
065 Уверен, что:
НЕ (-1) - это либо 0, либо 1
НЕ (0) - это либо -1, либо 1
НЕ (1) - это либо -1, либо 0
То что записано - инверсия
ИНВ(1) = -1
ИНВ(-1) = 1
ИНВ(1) = 0
-1 И -1 = 1
-1 И 0 = 0
-1 И 1 = -1
0 И 0 = 0
0 И 1 = 0
1 И 1 = 1
В случае логики
-1 ИЛИ -1 = -1
-1 ИЛИ 0 = -1
-1 ИЛИ 1 = 1
0 ИЛИ 0 = 0
0 ИЛИ 1 = 1
1 ИЛИ 1 = 1067 Вообще следует различать 2 понятия: они именуются по-разному, я обозначу их как битовые (тритовые) операции и логические операторы.
1. Битовые (тритовые) операции могут применяться к переменной любого типа, производятся над каждым разрядом без переносов. В синтаксисе языка C++ обозначаются:
& (логическое умножение)
| (логическое сложение)
^ (логическое исключающее сложение)
~ (логическое отрицание)
<< (логический сдвиг влево)
>> (логический сдвиг вправо)
Например
(10010011) & (00111101)= (00010001)
(00000001) << 4 = (00010000)
2. Логические операторы применяются только к логическим переменным. В C++ обозначаются:
&& (И)
|| (ИЛИ)
! (НЕ)
Если переменная не является логической, то принято, что 0 - ЛОЖЬ, все остальное - ИСТИНА
Я считаю, что для каждого из этих двух случаев нужно создавать свои отдельные правила. В последнем случае (именно он будет применяться в операторах IF и WHILE), наверно, следует ориентироваться на правила, используемые в реляционных СУБД.072 "Если переменная не является логической, то принято, что 0 - ЛОЖЬ, всё остальное - ИСТИНА"
Я думаю, что именно в этом вы заблуждаетесь, так как вновь уходите к двоичной системе.077 Я указал текущее положение вещей в некоторых языках программирования (C/C++, Python). Я как раз хотел сказать, что такой механизм не применим к троичному языку.
Здесь может быть такой вариант (пример для массива):
1. Массив, содержащий элементы - true
2. Массив, не содержащий элементы - false
3. Неопределенный массив (пустой указатель на массив) - null
Я уже встречал попытки внедрить троичную логику в современные языки. Так в частности VB 2005 содержит загадочное слово nothing, язык Python имеет встроенный литерал None.
Думаю неплохо будет в нашем языке для каждого типа данных как одно из возможных значений переменной использовать null. При инициализации переменной любого типа она должна по умолчанию устанавливаться в null (если не указано значение)084 "Думаю неплохо будет в нашем языке для каждого типа данных как одно из возможных значений переменной использовать null. При инициализации переменной любого типа она должна по умолчанию устанавливаться в null (если не указано значение)"
Это уже реализовано в Java.
Я считаю что всё-таки следует разделять троичную логику и троичную систему счисления. В случае логики 0 = undef, а в случае обычных типов 0 = 0.
160 One more : maybe "=?=" more likely than
''>==
068 Вариант типа "НЕ (1) - это либо -1, либо 0" для языка программирования не подходит: конструкция НЕ(1) должна вернуть что-то определенное, поэтому:
НЕ(1)=-1
НЕ(0)=0
НЕ(-1)=1073 Вообще-то, я подразумевал именно логическую составляющую. То есть, пусть есть светофор: Красный (-) Жёлтый (0) Зелёный (+). Если горит НЕ Красный свет, то какой свет горит ?
078 Вот мы и пришли к тому, что надо рассматривать операции сравнения (==, >, <, >=, <=, !=). Они тоже не всегда возвращают true или false: может быть еще и null. В частности любое сранение с null будет давать null:
null==true //null
null>5 //null
и даже
null==null //null.
Здесь мы приходим к 2 понятиям:
1. Операция сравнения (обычно обозначается ==, чтобы не путать с присваиванием =, а также >, <, >=, <=, !=). Диапазон возвращаемых значений: троичная логическая переменная (true, false, null)
2. Я называю это "оператор соответствия". Обычно обозначается "is" и его противоположность "not is". Работает на двоичной логике: возваращает true ли false.
Так
1. null==null и null!=null возвращают null
2. null is null возвращает true, а null is not null вернет false
Поэтому "НЕ красный" по отношению к какому-то цвету - это проверка на соответствие (точнее на его отсутствие) для какого-то состояния:
red is not red //false
yellow is not red //true
green is not red //true
Многие современные ЯП не имеют оператора is082 Такое ощущение, что мы размышляем не над созданием троичного ЯП, а пишем программку какому-то заморскому заказчику на его же языке.
Надо разработать терминологию для языка и использовать её, иначе получится такой хаос терминов и понятий, что мало кто в нём сможет разобраться. Что ещё хуже — нерусских терминов.
Прежде всего надо определить, какой из имеющихся двоичных языков берётся за основу. Я предлагаю Глагол (русский Оберон). Логический вид данных в нём именуется словом КЛЮЧ и имеет два значения: ВКЛ и ОТКЛ. Теперь же надо добавить третье, например, НЕОПР[еделено]. Можно использовать классические ИСТИНА и ЛОЖЬ, а третьим — НЕИЗВ[естно]. Или ДА и НЕТ. Присваивание в нём алголовское, то есть «:=», сравнение — «=», неравенство обозначается знаком «#» (лучше, конечно, использовать знак «≠», но для этого нужно раскладку клавиатуры редактировать).
081 Думаю, что Вы не совсем верный пример приводите, поскольку мы не выбираем между тремя равнозначными значениями (цветами светофора), а определяем истинность выражения. В последнем случае НЕ даёт определённый ответ (согласно таблице истинности для обращения (инверсии)).
071 В контексте операторов и операций троичного языка программирования (см. нижк)
074 Нашёл табличку с функциями: инверсия, и, или, следование, эквивалентность
086 Сразу оговорюсь, что здесь приводится не полный вариант сиснтаксиса языка, а лишь часть, касающая основ реализации троичной логики
Итак, предлагаются следующие конструкции:
Логический тип данных:
ЛОГ[ИЧЕСКИЙ]
диапазон значений:
ИСТИНА
ЛОЖЬ
НЕОПР[ЕДЕЛЕННО]
Оператор присваивания
:=
перем=ИСТИНА
Оператор сравнения (проверка на равенство)
==
возвращает логическую переменную
ИСТИНА==ИСТИНА //истина
ЛОЖЬ==ИСТИНА //ложь
НЕОПР==НЕОПР //неопределенно
Оператор сравнения (проверка на неравенство)
!=
возвращает логическую переменную
ИСТИНА!=ИСТИНА //ложь
ЛОЖЬ!=ИСТИНА //истина
НЕОПР!=НЕОПР //неопределенно
Таким образом мы исключаем знак "=" вообще, дабы не делали ошибок (для одних "=" ассоциируется с присваиванием, для других - с сравнением)
Прочие операторы сравнения: <, >, <=, >=
Также предлагается оператор, возвращающий > или < или == в зависимости от ситуации (предлагаемое обозначение >=< или >==<)
3>==<4 //ЛОЖЬ, интерпретируется как меньше
4>==<4 //НЕОПР, интерпретируется как равно
5>==<4 //ИСТИНА, интерпретируется как больше
В связи с этим можно ввести еще 3 равносильных литерала:
ЛОЖЬ МЕНЬШЕ
НЕОПР РАВНО
ИСТИНА БОЛЬШЕ
Оператор проверки соответствия:
ЯВЛ[ЯЕТСЯ]
возвращаемое значение: логическая переменная
Предполагается ИСТИНА или ЛОЖЬ, но для пользовательских типов может быть установлено НЕОПРЕДЕЛЕННО
ИСТИНА ЯВЛ ИСТИНА //истина
НЕОПР ЯВЛ НЕОПР //истина
Оператор проверки отсутствия соответствия:
НЕ ЯВЛ[ЯЕТСЯ]
ИСТИНА НЕ ЯВЛ ЛОЖЬ //истина
НЕОПР НЕ ЯВЛ НЕОПР //ложь
Про операторы ЕСЛИ и ЦИКЛ пока речи не идет, так как мы не разобрались еще с логикой, а они работают на логике.
Жду высказываний против :-)087 Принципиальных возражений нет. Но есть некоторые неясные моменты:
Зачем вводить оператор >==<, когда можно ввести функцию соответствующей проверки ОТНОШ(а,б): ЛОГ, которая вернёт -1, 0, 1, при этом функцию не обязательно вводить в язык, это можно сделать во внешем модуле. Вообще нужно стараться минимизировать язык, не внося в него лишних конструкций ( и устрашающих комбинаций типа == :) )
Не ясно чем ЯВЛ будет отличаться от простого равенства.
Как мне кажется таблички приведённой выше вполне достаточно, хотя я бы добавил туда некоторые элементы (такие как ИСКЛ ИЛИ, МАКС, МИН, ...).
P.S. Я бы всё-таки использовал не ==, а = (почему - читайте у Н.Вирта, у него на эту тему есть целый набор обширных статей) и вместо !=, соответственно, #. Но это, естественно, не принципиально.088 Насчет >==< согласен. Имеется в виду, что из-за 3 состояний логической переменной можно организовать подобный механизм возвращаемое значение библиотечной функции ИСТИНА, ЛОЖЬ, НЕОПР, которые интерпретируются как МЕНЬШЕ, РАВНО, БОЛЬШЕ.
ИСКЛ ИЛИ конечно необходимо, также как и И, НЕ (ИНВ - различия есть), а также (возможно) тритовые поразрядные операции (я писал об этом выше)
Что касается ЯВЛ. Для меня разделение == и ЯВЛ - необходимый механизм троичного программирования. Все дело в НЕОПР. Я ориентировался на троичную логику SQL. Любая операция с НЕОПР (например, сравнение) дает в результате НЕОПР, даже НЕОПР==НЕОПР дает в результате НЕОПР, поэтому мы не можем выполнить проверку логической переменной, что ее значение соответствует (или не соответствует) НЕОПР. В SQL эта проверка осуществляется специальными операторами is null и is not null, которые возвращают true или false соответственно (точнее в SQL таким образом просто проверяется выполнение условия, например, выборки). Предлагаемый аналог этого оператора - ЯВЛ работает на двоичной логике и для НЕОПР ЯВЛ НЕОПР вернет ИСТИНА (в отличие от ==, который вернет ЛОЖЬ). То есть ЯВЛ не предполагает возвращение НЕОПР.089 В связи с этим предлагаю работу операторов ЕСЛИ, ЦИКЛ, ВЫБОР основывать именно на логике оператора ЯВЛ, а не ==
Также для ЯВЛ лучше придумать специальный символ092 Тогда зачем нужен оператор == ??? Чтобы был?
091 Не следует пытаться использовать костыли SQL. Нужно нормально относится к логической операции равенства работающей в троичной логике. и почему равенство должно вернуть ложь? Обрати внимание на табличку выше, я её не случайно привёл. Она из математической работы посвящённой логике Аристотеля (трочиной). И там чётко определено:
(ИСТИНА = ИСТИНА) -> ИСТИНА
(ИСТИНА = НЕОПР) -> НЕОПР
(ИСТИНА = ЛОЖЬ) -> ЛОЖЬ
(НЕОПР = ИСТИНА) -> НЕОПР
(НЕОПР = НЕОПР) -> ИСТИНА
(НЕОПР = ЛОЖЬ) -> НЕОПР
(ЛОЖЬ = ИСТИНА) -> ЛОЖЬ
(ЛОЖЬ = НЕОПР) -> НЕОПР
(ЛОЖЬ = ЛОЖЬ) -> ИСТИНА094 Виноват, описка. Имел в виду
НЕОПР==НЕОПР //неопределенно
НЕОПР ЯВЛ НЕОПР //истина
Все по делу, но не согласен только с тем, что
(НЕОПР = НЕОПР) -> ИСТИНА
Любая операция с НЕОПР должна возвращать НЕОПР095 Категорически не согласен.
И с точки зрения логики и сточки зрения теории множеств, НЕОПР = НЕОПР есть ИСТИНА ибо НЕЧТО всегда есть НЕЧТО. Это классика. Вообще, как я уже писал ранее, любой бинарный оператор (x OR y, x AND y, x XOR y, и т.д.) можно представить в виде L(x, y) и построить таблицу соответсвия L = ... в зависимости от x и y. И таких комбинаций набигает 19683 штуки. При этом части комбинаций математики уже поставили в соответствие определённые операции (min, max, or, xor, and, equ, и т.д.)... поэтому я предлагаю и использовать эти СТАНДАРТНЫЕ комбинации.096 Ну если так, то конечно оператор ЯВЛ можно выкинуть, поскольку он становится не нужен.
Не совсем понятно, откуда взялось число 19683 (3^9)097 Попробую объяснить. Используем метод индукции :).
Рассмотрим БИНАРУНЮ функцию от двух переменных. Её результат можно представить в виде таблицы 2x2, где каждая ячейка будет принимать значение 0 или 1 в зависимости от используемой функции. Всего возможно 16 уникальных вариантов таких таблиц (2^4).
Примеры таблиц: (& - и, v - или, = - тождество, 1 - всегда 1, 0 - всегда 0, x - исключающее или)...
&.0.1...v.0.1...=.0.1...1.0.1...0.0.1...x.0.1
0.0.0...0.0.1...0.1.0...0.1.1...0.0.0...0.0.1
1.0.1...1.1.1...1.0.1...1.1.1...1.0.0...1.1.0
и так далее (ещё 10 вариантов)...
Теперь рассмотрим троичный случай. Каждая переменная принимает одно из трёх значений (-, 0, + или -1, 0, +1 или 2, 0, 1) - следовательно каждая таблица будет представлять собой матрицу 3х3, где каждая ячейка находится в одном из трёх состояний (3^9)
Пример:
&.2.0.1...v.2.0.1...=.2.0.1...1.2.0.1...0.2.0.1...x.2.0.1
2.1.0.2...2.2.2.1...2.1.0.0...2.1.1.1...2.0.0.0...2.1.2.0
0.0.0.0...0.2.0.1...0.0.1.0...0.1.1.1...0.0.0.0...0.2.0.1
1.2.0.1...1.1.1.1...1.0.0.1...1.1.1.1...1.0.0.0...1.0.1.2
P.S. рекомендую http://aymara.org/ternary/ternary.pdf - краткое введение в троичную логику (правда на английском)098 Вспомнил! Что-то такое я уже проходил. Двуместных функций двоичного аргумента 16, и у каждой есть свое название. Просто не ожидал, что функций троичного аргумента окажется так много!!!
162 By the way, FUZZY logic can be represented on one or more TRITs as degrees of truth (or probabilities) in range not between 0 and 1 but between ~1*n and +1*n , where "n" is number of TRITs. Accuracy of value depends on "n" . Further rules are described in theory of FUZZY logic, for example:
NOT x = (1 - truth(x)) , e.t.c.
One more : maybe "=?=" more likely than''>==
159 One more : maybe "=?=" more likely than
''>==
158 One more : maybe "=?=" more likely than
''>==
090 Для комментариев предлагаю (на первое время) широкий спектр, взятый из популярных языков:
1. однострочный (до конца строки)
КОММЕНТ комментарий
РЕМ (от слова "ремарка")
// комментарий
' комментарий
# комментарий
-- комментарий
2. многострочный
/* комментарий */
(* комментарий *)
<!-- комментарий -->093 Мне кажется не следует слишком разнообразить. Достаточно остановиться на (* *) или /* */
099 Над выбором слова для среднего значения надо ещё подумать, поскольку, например, для сравнения двух чисел будет весьма нелогично в случае равенства выдавать значение, называемое «неопределено» (или, тем более, «неизвестно»). С ним же возникает некоторая путаница в логике при использовании слова ИНАЧЕ. В конце концов, это слово обозначает строго определённое значение, а неизвестным может являться лишь результат решения определённой группы задач, на который указывает (при том весьма условно) это логическое значение.
В продолжение темы об условии. Тут тоже надо подумать над выбором слов.
Я предлагаю такую схему условия:
ЕСЛИ усл ТО
действ1 (* усл = ИСТИНА *)
[В ОБРАТНОМ СЛУЧАЕ]
действ2 (* усл = ЛОЖЬ *)
[В СЛУЧАЕ НЕОПРЕДЕЛЁННОСТИ]
действ3 (* усл = НЕОПР *)
КОН
Это же можно записать, используя слово ИНАЧЕ. Либо так:
ЕСЛИ усл ТО
действ1 (* усл = ИСТИНА *)
[В ОБРАТНОМ СЛУЧАЕ]
действ2 (* усл = ЛОЖЬ *)
ИНАЧЕ
действ3 (* усл = НЕОПР *)
КОН
Либо так:
ЕСЛИ усл ТО
действ1 (* усл = ИСТИНА *)
[В СЛУЧАЕ НЕОПРЕДЕЛЁННОСТИ]
действ3 (* усл = НЕОПР *)
ИНАЧЕ
действ2 (* усл = ЛОЖЬ *)
КОН
Условие можно записывать и в привычной для двоичной логики форме:
ЕСЛИ усл ТО
действ1 (* усл = ИСТИНА *)
ИНАЧЕ
действ2 (* усл = ИСТИНА ИЛИ усл = НЕОПР *)
КОН
Следует упомянуть и указание АЕСЛИ, которое заменяет конструкцию ИНАЧЕ ЕСЛИ. В троичном ЯП АЕСЛИ также может заменять ИНАЧЕ при наличии вложенного условия:
ЕСЛИ усл1 ТО
действ1 (* усл1 = ИСТИНА *)
[В СЛУЧАЕ НЕОПРЕДЕЛЁННОСТИ]
действ2 (* усл1 = НЕОПР *)
АЕСЛИ усл2 ТО
действ3 (* усл1 = ЛОЖЬ; усл2 = ИСТИНА *)
...
КОН
Предлагаю обсудить предложенный мною вариант. Если он является приемлимым, то надо выбрать подходящие слова вместо [В ОБРАТНОМ СЛУЧАЕ] и [В НЕОПРЕДЕЛЁННОМ СЛУЧАЕ].100 > действ2 (* усл = ИСТИНА ИЛИ усл = НЕОПР *)
Имел ввиду усл = ЛОЖЬ ИЛИ усл = НЕОПР.101 А нельзя выяснить сначала определено ли условие и в случае его определенности оно будет либо истина либо ложь, то есть выглядело бы след. образом:
ЕСЛИ усл = НЕОПР ТО
действ 1
ИНАЧЕ
ЕСЛИ усл=ИСТИНА TO
действие2
ИНАЧЕ
действие3104 А как выполняются арифметические сравнения?
105 Это весьма интересный вопрос. Видимо, обычные арифметические сравнения будут давать двоичный ответ. Для троичного сравнения надо ввести специальное служебное слово. Выглядеть это будет примерно так:
А СРАВН Б (* если А > Б, то ИСТИНА, и т.д. *)
Впрочем, это сравнение вполне заменяет традиционные, которые следует оставить для удобства.106 А по моему арифметическое сравнение будет давать как раз троичный ответ: больше, меньше, равно :)
107 Так и то, и другое сравнение является арифметическим. Я просто отдельно писал про сравнения «=», «», «≤», «≥», «≠». Разве они могут возвращать троичный ответ? Разве может одно число быть одновременно и не равным другому, и не не равным ему?
108 На самом деле как можно,
например нужно сравнить две переменные:
сравнить(а,б) делать если a меньше б; делать если а равно б; делать если а больше б109 Ну так примерно это же я и предложил выше, но при этом предложил оставить и традиционные для двоичных языков сравнения, которые в процессе компиляции программы будут преобразовываться в троичное.
110 Ну тут просто без логических понятий: истина, неопределенность, ложь.
Так можно считать что
истина = +
ложь = -
неопределенность = 0
Например:
сравнить(неопределенность) пусто; действие выполнится; пусто111 Всё ж нелогично выглядит ситуация, когда сравнение возвращает неопределённость. На мой взгляд, лучше подошло бы именование среднего значения другим, средним или третьим вариантом, но никак не неопределённостью или неизвестностью.
112 Тогда так:
x = неопределённость;
сравнить(х, неопределенность) не выполнится; выполнится; не выполнится113 Я имею ввиду немного другое. Речь о самом слове «неопределённость». Какие бы конструкции из сравнения мы бы ни построили, ему в любом случае придётся дать логический ответ, и в случае равенства он будет равен среднему значению, именуемому выше неизвестностью. На мой взгляд, такое именование не совсем верно, при том не только для сравнения (потому одним исправлением конструкции сравнения вопрос не решится), но и для всей троичной логики.
Про конструкцию. В части случаев её весьма удобно будет применять. Но в другой части (в основном в выражениях) для её употребления придётся использовать дополнительную переменную и значительно усложнять вид выражения. Не лучше ли в этих случаях применять конструкцию "А СРАВН Б"?
114 Я уже предлагал компактный вариант для условных операторов. Если нам надо рассмотреть все 3 случая отдельно, то лучше воспользоваться оператором ВЫБОР:
ВЫБОР (усл):
{
ЛОЖЬ: операторы;
НЕОПР: операторы;
ИСТИНА: операторы;
}
Все четко и понятно. Все три возможных значения равноправны, можно менять их порядок или даже пропускать. Если же надо обработать одно условие и его альтернативу, то тогда применяетмя один из ЕСЛИ:
ЕСЛИ_ИСТИНА (усл) операторы;
ЕСЛИ_НЕОПР (усл) операторы;
ЕСЛИ_ЛОЖЬ (усл) операторы;
пример.
ЕСЛИ_ИСТИНА (перем1==перм2): Вывод("истина");
ИНАЧЕ Вывод ("ложь или неопределенно");
Что касается оператора СРАВН. Его луше сделать функцией стандартной библиотеки, возвращающей логическое значение:
к==л НЕОПР
к>л ИСТИНА
к,115 > ВЫБОР (усл): { ЛОЖЬ: операторы; НЕОПР: операторы; ИСТИНА: операторы; }
Это весьма неудобный вариант, превращяющих простое условие в конструкцию выбора (у которой есть своё назначение).
> ЕСЛИ_ИСТИНА (усл) операторы; ЕСЛИ_НЕОПР (усл) операторы; ЕСЛИ_ЛОЖЬ (усл) операторы;
Не многим лучше. Разве троичная логика не позиционируется как более близкая к естественной, нежели двоичная? Так зачем создавать кучу неудобных служебных слов, отдаляющих троичный язык от привычного людям порядка слов (когда ЕСЛИ...ТО Истина ИНАЧЕ Не истина КОН)?
> Его луше сделать функцией стандартной библиотеки
Почему? Это же элементарная арифметическая и логическая операция.
> 5==НЕОПР /* НЕОПР */
Согласен.
> Еще надо точно определить насчет НЕОПР==НЕОПР - это ИСТИНА или НЕОПР.
Тут вопрос в самой сути значения. Если не рассматривать то, что мы его называем неопределённостью, то НЕОПР=НЕОПР вполне себе ИСТИНА. В обратном же случае нам действительно неизвестно, равны ли эти значения, поскольку они неопределены (суть неизвестны), поэтому НЕОПР. Так что ещё раз предлагаю подумать над верностью выбора наименования для среднего значения.116 Снова вернулись к тому, что с одной стороны есть оператор == и есть оператор ЯВЛ
НЕОПР==НЕОПР - НЕОПР
НЕОПР ЯВЛ НЕОПР - ИСТИНА
НЕОПР==5 - НЕОПР
НЕОПР ЯВЛ 5 - ЛОЖЬ
Оператор ВЫБОР
ВЫБОР (усл):
{
ЛОЖЬ: операторы;
НЕОПР: операторы;
ИСТИНА: операторы;
}
работает на основе оператора ЯВЛ, а условие внутри оператора ЕСЛИ
ЕСЛИ (5==НЕОПР)
работает по принципу оператора ==117 > НЕОПР==НЕОПР - НЕОПР
Забудем, что НЕОПР — это неопределённость. Это 0. Но чтобы не сбивать с толку сутью значения нуля, назовём его X. Так с какой стати нам неизвестно, что X = X?118 Конечно что-то всегда равно самому себе, если только оно неопределено.
То есть получается, что все упирается в небходимости выбрать правильное для НЕОПР
:-)119 > То есть получается, что все упирается в небходимости выбрать правильное для НЕОПР
Отнюдь. 0 = 0 есть ИСТИНА. А о том, во что сейчас упирается ход нашего обсуждения, я писал выше.164 если ~1 false или нет ,+1 true или да , то для 0 лучше всего подойдёт не undefined или unestimated , а что-то вроде "несклонившееся ни в пользу да, ни в пользу нет" ... Как это кратко обозначить надо подумать ...
165 Здесь всё зависит от ваших целей. Интерпретаций терьего состояния пруд пруди, но строгую проверку на непротиворечивость и содержательность проходят далеко не все.
120 Снова про среднее значение. Разобравшись с ним, можно будет оформить предварительную версию основной части троичного высокоуровневого языка. Ведь с арифметическими действиями, циклами и (будем считать) условиями разобрались.
Логических значений может быть весьма много. Кроме истины и лжи может быть «не истина, и не ложь», «и истина, и ложь», «значение неизвестно или нефиксировано», «значение не может быть определено» и т.д. Все эти значения в троичной логике объединены в одно. Снова приходим к выводу, что называть его неопределённостью в большей части случаев неправильно. Но как же тогда его называть?121 Если мы говорим про троинчую логику в троичной симметричной системе, то всё равно всё сведется к -, 0, +, не так ли?
122 Именно так. Но вот путаница при неверном выборе обозначения уже дала о себе знать: как в случае с 0 = 0 есть + или 0 (хотя очевидно, что это +, при использовании термина «неопределённость» возникает неразбериха) или в случае со сравнением, когда равенство выражений обозначается словом «неопределённость». Но наиболее полно себя этот вопрос выявил при разработке конструкции условия.
То есть сейчас надо либо подобрать несколько служебных слов (для логического значения 0 и два слова для условия) либо придумать другую конструкцию ЕСЛИ (хотя в этом случае она врядли будет удобнее).123 А как вам так?
0 == 0 -> 0
0 == 5 -> +
0 == -5 -> -126 Если уж искать компромиссный вариант, то можно пойти по стопам разработчиков, например, языка Си: они вообще отказались от логического (для них - булевского) типа. Мы можем условиться, что отрицательное - ЛОЖЬ, положительное - ИСТИНА, 0 - есть 0, как его не называй
127 Поясните мне пожалуйста, почему вы так упорно пытаетесь игнорировать математиков, которые давно уже разработали весь математический аппарат троичной логики. Тот же "Льюис Керолл"?
161 One more : maybe "=?=" more likely than
''>==163 если ~1 false или нет ,+1 true или да , то для 0 лучше всего подойдёт не undefined или unestimated , а что-то вроде "несклонившееся ни в пользу да, ни в пользу нет" ... Как это кратко обозначить надо подумать ...
129 Хотелось бы упомянуть что ДССП фактически является троичным языком программирования (пусть и реализован на двоичной архитектуре)
130 Я тут недавно подумал: хорошо бы было, чтобы в троичном языке программирования массивы нумеровались от нуля и можно было заполнять их как в одну, так и в другую сторону. Тогда можно будет обращаться к элементам с отрицательным смещением:
for I := -364 to 364
arr[I] := 0;
Возможно, при таком подходе можно будет убыстрить некоторые алгоритмы и, учитывая, что в троичном компьютере не будет беззнаковых чисел, этот подход мне кажется более обоснованным, потому что так можно будет задействовать весь диапазон чисел (для трайта с 6 тритами 3^6 = 729), а не только положительные числа.
131 Вполне уместно.
Беззнаковые чила могут быть и в троичном симметричном коде — это смотря как интерпретировать.132 Ну да, могут быть. Это если ------ принять за ноль, а не за -364. Но это уже будет неестественно, так же, как и представление знаковых чисел в двоичной системе. Даже может быть и хуже.
Хорошо бы, чтобы беззнаковых чисел вообще не было, чтобы не загромождать процессор командами-дубляжами (как в x86: есть ja - команда "больше" для беззнаковых и jg для знаковых и др.), а опираться только на знаковые числа, на положительное и отрицательное смещение. Кстати, тогда может и команда побитового сдвига одна будет.133 Как вам такая адресация элементов массива:
0 1 2 3 ......... 363 364 365 ........ 727 728 729
0 -729 -728 -727 ......... -365 -364 -363 ........ -3 -2 -1134 Точнее так:
0 1 2 3 ......... 363 364 365 ........ 726 727 728
0 -728 -727 -726 ......... -365 -364 -363 ........ -3 -2 -1 ”
Прошу прощения, цифры сдвинулись, но, надеюсь, понятно: нумерация отрицательными числами идет в обратном порядке, то есть элемент -727 и 3 - один и тот же элемент
Ваш вариант
-343 -342 -341 ...... -3 -2 -1 0 1 2 3 ......... 341 342 343
красив, но практической целесообразности того, что нулевой элемент массива в центре, а не в начале, я не вижу
136 Хотелось бы дополнить, отрицательные индексы в массивах реально используется в некоторых языках программирования.
Например, массив array = [1, 2, 3]
array[0] = array[-3] = 1
array[1] = array[-2] = 2
array[2] = array[-1] = 3
Т.е. первый элемент можно получить как по 0 индексу так индексу равному отрицательной длине массива.137 Собственно это я и имел в виду
135 Массив по своей сути контейнер, который рестет только вперед. Контейнер, растущий в обе стороны называется деком, причем нулевым является всегда крайний левый элемент
138 Массивы бывают двух видов. Статические и динамически.
1. Для статического массива нумерация не очень существенная. По сути программист может задать ее произвольно (например, от -7 до 12)
2. Для динамического массива действительно хорошо предусмотреть рост в обе стороны, но при этом невозможно будет использовать схему типа:
array[0] == array[-3]
array[1] == array[-2]
array[2] == array[-1]
хотя лично мне она кажется прямым следствием использования современного способа представления отрицательных чисел в двоичной ЭВМ (если уж вы нумеруете с конца, начиная с -1, то нумеруйте и в начале, начиная с 1, а не с 0)139 Если использовать массив, растущий в обе стороны и задействовать отрицательные индексы, то придется отказаться от такой практики.
При поиске элемента в массиве (или строке) иногда используется такой подход: если элемент найдет, то возвращается его индекс, если не найден - возвращается -1 (или 0, если нумерация идет с 1).
Впрочем, описанный метод не является хорошим, поэтому использование отрицательных индексов - хороший повод вывести его из моды :-)140 Да, давно пора возвращать объект: "искомый индекс" или "ошибка поиска".
141 В таким случаях я приучил себя использовать механизм исключений
142 Зря. Исключения - безусловное зло :) Все исходы всегда должны быть описаны явно.
143 Исключения как раз и позволяет этого добиться не загаживая код
144 Я высказываю лишь свое мнение.
Плюсы исключений:
1. Позволяют отделить обработку данных от обработки ошибок, которые при этом возникают
2. Разгружают код от лишних конструкций типа "Если КодОшибки=.... то"
Недостатки:
1. Высокие накладные расходы процессорного времени и памяти на обработку исключений (но в интерпретируемых языках это стараются оптимизировать)
"Исключения - не панацея" ("ООП в С++", Лафоре)148 > 1. Высокие накладные расходы процессорного времени
Странно, вот как раз процессорного времени должно уходить чуть-чуть меньше.149 Ничего странного, накладные расходы вызваны как раз тем чем и плюсы исключений, а именно покрытием любой области кода, а не только конкретного участка кода.
150 Во всех тестах исключение работает быстрее чем проверка результата.
151 Пруфлинк?
152 Пожалуйста:
- http://www.google.ru/153 Я думаю, что как и я, serg под исключениями понимает: http://java.sun.com/docs/books/tutorial/essential/exceptions/definition.html
Следовательно как и было уже сказано нами исключения полезная и удобная штука,
но по производительности уступает обработке кодов возвратов.
В http://www.google.ru/ много на эту тему.
Также простая программа сравнения двух подходов показывает, что исключения медленнее в 5 раз и более чем коды возврата, к сожалению.154 Я по привычке рассматривал вариант реализации механизма исключений в приложении к Си++. Не могу понять почему такая такая большая разница между реализациями в Си++ и в Яве. Хотя, возможно дело в том, что я описывал ситуацию, когда исключения не происходит - в этом случае нет лишних принудительных проверок результата и код с использованием фактически работает на пару процентов быстрее.
155 Подход с исключениями не зависит от языка, это шаблон проектирования приложений.
Несомненно если исключение не происходит то и работы по его обработке не будет.156 
Я плохо знаком с ассемблером, но, на сколько мне известно, обработка исключений компилируется в машинный код примерно так: один оператор С++ преобразуется в 2 машинные команды:
1. сама операция (например сложение)
2. проверка регистра флагов на наличие ошибок (например переполнение аккумулятора при сложении)
и это для КАЖДОЙ команды.
Если мы будем использовать операторы ЕСЛИ, то наверняка будем окружать ими не каждую инструкцию, а только те, где ПО-НАШЕМУ МНЕНИЮ МОГУТ произойти ошибки (но точно не все). Таким образом, ГЕНЕРАЦИЯ исключений медленнее.
НО!
В интерпретируемых языках (например, Python) стараются оптимизировать исключения. Об этом можно судить хотя бы потому, что при ошибке вылетает не программа вместе с интерпретатором, а только программа (интерпретатор продолжает работать)
145 Или можно возвращать НЕОПРЕДЕЛЕНО. Троичная логика может и тут пригодиться
146 Практически во всех языках есть конструкция nil/null — неопределенно/ничего
но оно не имеет ничего общего с ошибкой, это полноправное значение, которое часто используется.147 Согласен, что не имеет ничего общего с ошибкой, но то, что элемент не найден в массиве - это не ошибка, а вполне нормальная ситуация
177 Симметричным n-арным языком программирования является Smalltalk.
У класса есть выделенный метод-конструктор, и есть выделенный метод --- "doNotUnderStand: methodName withArguments: arguments" (т.н. метод DNU). Метод DNU играет роль нуля, остальные методы (кроме конструктора) симметричны по своей функции.
Например, класс с методами
+
DNU
-
может символизировать
+
0
-178 Класс без метода DNU символизирует логику без нуля (например, бинарную):
+
-179 Однако в этом случае DNU содержится в предке данного класса, т.е. Object или Protoobject или в каком-либо другом предке. То есть в Смолтоке все инстансы всех классов имеют нулевое (непонимательное) значение логики.
180 Если кому нужен свободно-бесплатный Смолток для экспериментов на двоичных машинах, можно взять с http://squeak.org (Pharo или Squeak).
181 Тут скорее арифметика без нуля.
История сообщений
24 января
9 января
8 января
7 января
2011
16 декабря
15 декабря
2009
28 декабря
27 декабря
26 декабря
25 декабря
22 декабря
21 декабря
25 июля
24 июля
20 июля
25 февраля
24 февраля
21 февраля
20 февраля
14 февраля
13 февраля
12 февраля
11 февраля
- Alexander Obukhov
- Русский
- Alexander Obukhov
- Русский
- Alexander Obukhov
- Русский
- Alexander Obukhov
- Русский
- Alexander Obukhov
- Русский
- Naty
- Naty
- Русский
10 февраля
28 января
27 января
26 января
25 января
24 января
- Дмитрий
- Дмитрий
- Дмитрий
- Дмитрий
- Serg
- Serg
- Serg
- Serg
- Serg
- Naty
- Дмитрий
- Serg
- Serg
- Serg
- Serg
- Serg
- Serg
- Русский
- Дмитрий
- Дмитрий
- Бармалейкин
- Русский
23 января
22 января
21 января
2008
18 декабря
17 декабря
16 декабря
18 ноября
17 ноября
12 ноября
11 ноября
8 ноября
5 ноября
- Alexander Obukhov
- Alexander Obukhov
- Alexander Obukhov
- Alexander Obukhov
- Alexander Obukhov
- Alexander Obukhov
