Zealint писал(а):
Result.h имеет размер 40 бит?
72-64 = 8 бит.
Zealint писал(а):
Но оставляет проблему tab-hell (так я буду её называть), когда открываешь чужой код, а там... приходится бежать за тазиком, чтобы на пол не вырвало.
Таких мест полно и без табуляций. В данном случае важно, что визуальное представление не оказывает непосредственное влияние на формальную корректность.
Zealint писал(а):
Да. Только слово "условно" тут лишнее.
Нет, совсем не лишнее. Если мы присваиваем результат умножения 32-битных чисел 32-битному числу, то потенциально теряем старшие разряды. Т.е. такое присваивание нельзя считать действительно безопасным, но и замечания выводить нехорошо.
Zealint писал(а):
Тут два варианта: либо преобразование типов действительно безопасно, либо, создавая новый тип, мы пишет ещё 100 функций его безопасного преобразования куда нужно. Небезопасное приведение (то, которое может привести к неожидаемой образованным программистом потере точности), нужно исключить из языка.
Да нет же, вариантов на самом деле три: опасное, безопасное и условно-безопасное.
1. Опасное - приведение целого числа к типу "указатель".
2. Безопасное - преобразование 32-битного числа в 64-битное.
3. Условно безопасное - преобразование 32-битного числа в 16-битное.
Zealint писал(а):
Хорошо, я подумаю над этим. Точно ли, что компилятор всегда сможет определить размер промежуточных результатов правильно?
Я полагаю, да, всегда может.
Zealint писал(а):
Да я, в общем-то, согласен. Просто жалко. Представьте, таблицу из 16-теричных чисел, которую хочется выровнять и сделать красивой, чтобы столбцы ровными были, и придётся каждое из чисел начинать с 0 или с пробела. Либо будет лишний 0 где-то, либо «рваная» граница столбца из-за пробелов.
А если у вас таблица десятеричных чисел? А если двоичных чисел? Как раз 0 здесь совсем не лишний.
Zealint писал(а):
Иногда хочется выйти из блока кода, который не в цикле, собственно, я и привёл такой пример, в котором программист вынужден делать фальшивый цикл (do..while (false)) ради такой возможности. Делать это с помощью goto плохо, это требует создавать метку после блока. Данная метка кажется явно лишней.
Вы правильно заметили -
иногда. Вот в этих
редких случаях использование оператора goto вполне оправдано. В большинстве же случаев можно просто реорганизовать условные операторы так, чтобы потребности в goto не возникало. А вот выходить из циклов приходится часто.
Zealint писал(а):
Ну, если синтаксис break с условием уже устоялся, тогда лучше именовать циклы.
Код:
first : for ( ) {
second : for ( ) {
break [first] ( условие );
}
}
Чем это отличается от goto? Наличием условия и тем, что метка находится перед циклом, можно давать осмысленные имена циклам, не нужно делать метку за циклом, и вообще посимпатичнее.
Оно может быть и посимпатичней, но несколько нарушает логику. В данном случае first и second - метки, а значит, их использование воспринимается как потенциальный переход НА них. То, что с оператором break они работают по другому, является исключением, а чем больше исключений, тем хуже структура языка. Оператор goto в данной ситуации не добавляет ни одного лишнего символа и не привносит в правила исключений.
Zealint писал(а):
Квадратные скобки в break как бы намекают на свою необязательность и не конфликтуют не с чем другим, если Вы в своём синтаксисе используете их примерно так же, как они сейчас используются в C++.
Логично. Неплохая идея.
Zealint писал(а):
Я надеюсь, Вам не пришло в голову, например, передавать параметры в функцию через квадратные скобки, как это пришло в голову Стивену Вольфраму?
Не вижу разумных оснований для такого извращения.
Zealint писал(а):
Yoda писал(а):
- Размер результата взятия остатка от деления равен размеру делимого.
Почему? Остаток же не превосходит частного.
Да, действительно, ошибся. Размер результата взятия остатка от деления равен размеру делителя.
Zealint писал(а):
Кстати, остаток от деления «математический» или «программистский»?
А в чём разница?
Zealint писал(а):
Yoda писал(а):
- Размер результата возведения в степень равен 128 бит независимо от размеров операндов.
Хм... 2^1000 не будет считать? Язык должен поддерживать бесконечный целый тип, и если результат влезет только в него, то его-то и нужно использовать.
Тут вот какое дело. Бесконечный целый тип поддерживается не компилятором, а библиотеками, а это принципиальная разница. Поэтому, чтобы возводить в такую степень, надо сначала основание или показатель привести к бесконечному типу, тогда вместо встроенного возведения будет вызвана функция из библиотеки.
Zealint писал(а):
Кстати, у Вас будет оператор возведения в степень? Это как бы не совсем отражает архитектуру и неочевиден вопрос его эффективной реализации. Есть много вариантов: Вы который предпочитаете?
Да, будет. Дело тут не столько в эффективности реализации, сколько в удобстве записи. Я думаю, ** - будет достаточно понятно и удобно.
Zealint писал(а):
Должны быть типы данных, отражающие размерность регистров ЭВМ. Int8, int16, int32, int64. Со знаком и без него. Как мы их будем называть – это сейчас не важно. Эти типы данных реализуются аппаратно.
Точно. Более того, в моей концепции исключён тип данных int без указания размера. Программист должен чётко понимать, какой диапазон ему требуется.
Zealint писал(а):
Должны быть типы данных, которые имеют больший размер. Int128, int256 и некоторые другие (пояснения ниже). Эти типы реализованы программно.
int128 - да, другие нет. Причина вот в чём. 64 бита - максимальная разрядность, которая может быть широко востребована, следовательно это последний тип, который действительно имеет смысл реализовывать полностью аппаратно. int128 рассматриваю в качестве
последнего программно реализованного встроенного типа по одной причине, - только как основа для библиотеки бесконечной точности. Цепочные операции без расширения разрядности (то есть во всех традиционных языках программирования) можно реализовать только с потерей эффективности. Например, если нам потребуется программная реализация 128-битных чисел в традиционных ЯВУ, мы должны прибегнуть к 32-битным умножениям с переносом старших половин, несмотря на то, что архитектура может поддерживать 64-битные операции. То есть, ЯВУ накладывает искусственные ограничения на ровном месте. Введение int128 даёт красивую возможность избежать этого. int256 (и бОльшие размеры) - явно лишние.
Zealint писал(а):
Представьте, что появился регистр размером 128 бит (ну мало ли). Тогда тип int128 из искусственного должен перекочевать в естественный для нашего языка, но при этом абсолютно все программы, которые можно написать с его участием, будут компилироваться правильно.
Хотя мне сложно себе представить массовую архитектуру с аппаратной поддержкой 128 бит (я бы даже сказал, что вряд ли такая появится, но буду осторожен), но в этом случае ничего принципиально не сломается. Будет введён программный тип int256 и вся схема будет прозрачно расширена до этого типа.
Zealint писал(а):
До каких пор нам нужны типы int128, int256, int512... ? Здесь нет общего мнения.
Общего нет. Моё личное мнение таково: последний аппаратный - int64, int128 - софтверный, далее - библиотечный бесконечной точности. Если архитектура не поддерживает 64-битную арифметику аппаратно, то оба типа (64 и 128) реализуются программно, но оба должны обязательно присутствовать.
Zealint писал(а):
Дело вот всё в чём. Есть у нас GMP и MPIR - самая лучшая на сегодня длинная арифметика. Но когда мы заведомо знаем, что наши числа не превосходят 1024 бита, то искусственно созданный тип такого размера будет выигрывать по скорости и по памяти у GMP. Если нам нужно 2048 и больше, то здесь выигрыш уже будет менее существенным, и игра не стоит свеч. Число 1024 я тут взял навскидку, можно провести исследование и отыскать эту «золотую середину», но сейчас это не нужно. Общая мысль такая: нужно отыскать баланс по эффективности и создать достаточно целых типов данных, чтобы обеспечить программиста эффективным инструментом. В моей практике приходилось работать с int512 и по эффективности рвать GMP на части благодаря этому.
Я думаю, идеальным в данной ситуации было бы как раз позволить пользователю определять эти типы самостоятельно и не резервировать эти имена.
Zealint писал(а):
Здесь нужно придерживаться имеющихся стандартов и возможностей ЭВМ. То есть создать типы real32, real64, real80 и пока успокоиться на этом, зарезервировав все подобные названия типов на будущее.
Опять же, всё правильно, за исключением того, что резервировать отсутствующие не надо. Иначе пользователь не сможет определить их своими библиотеками.
Zealint писал(а):
Должен быть тип real, который объемлет все плавающие типы и имеет бесконечную точность.
С арифметическими операциями всё в порядке, а вот иррациональные уже не сделать. Возвести в нецелую степень уже не получится. Моё мнение таково, что по аналогии с расширением аппаратного 64-битного типа до программного 128-битного, возможно, нужна поддержка программного типа float256, но не более того.
Zealint писал(а):
Должен быть тип rational, который содержит числитель и знаменатель типа int. То есть дробь с бесконечной точностью.
Исключительно в качестве стандартной библиотеки. Кстати, да, забыл, целый тип бесконечной точности также должен входить в СТАНДАРТНУЮ библиотеку.
Zealint писал(а):
Нужен ли быть, например, тип rational32, числитель и знаменатель которого будет int32? Это вопрос интересный. Дело в том, что иногда возникает необходимость в таких типах, когда мы знаем, что результат будет довольно безобидным. Но проблема в том, что промежуточные данные (как для числителя, так и для знаменателя), особенно после многократного сложения/вычитания дробей, могут уйти далеко за пределы int32, что совершенно неочевидно предсказывается.
Я думаю, таких типов не надо, числитель и знаменатель должны иметь бесконечный диапазон. Редко когда числитель/знаменатель вписываются в такие маленькие диапазоны. Если пользователь уверен в диапазонах, пусть создаёт свой тип.
Zealint писал(а):
Аналогично рациональным. Это может быть немного печально, но придётся для них сделать суффикс i. Будем писать 2+3i.
Не вижу повода для печали. Нормальная запись.
Zealint писал(а):
Проблема здесь в том, что в основе комплексных чисел может лежать как число с плавающей точкой, так и рациональное. И нужно хорошо подумать, как эту грустную новость сообщить компилятору.
Да не надо рационального комплексного. Встроенный тип - только на основе плавающей арифметики.