OberonCore
https://forum.oberoncore.ru/

LONGINT => INTEGER
https://forum.oberoncore.ru/viewtopic.php?f=35&t=6580
Страница 1 из 1

Автор:  olegr [ Суббота, 07 Март, 2020 19:39 ]
Заголовок сообщения:  LONGINT => INTEGER

Здравствуйте,
помогите разобраться, был уверен, что если переменной типа LONGINT присвоить выражение с переменными типа INTEGER, то результат будет в диапазоне допустимых значений типа LONGINT, вот пример где я запутался.
Код:
MODULE Kern;
IMPORT L := StdLog;

PROCEDURE Do*;
VAR
   block,sector,number:   INTEGER;
   total:   LONGINT;
BEGIN

   L.Int(MAX(INTEGER)); L.Ln;
   L.Int(MAX(LONGINT)); L.Ln;

   block := 8; sector := 512; number := 10000000;
   total := block * sector * number;
   L.Int(total); L.Ln;
   
END Do;

BEGIN

CLOSE

END Kern.

Kern.Do

результат вывода в журнал :
2147483647 - это MAX(INTEGER)
9223372036854775807 - это MAX(LONGINT)
-1989672960 - а это как ведь должен же быть 40960000000 или total: LONGINT стал INTEGER ?


Что не так?

Автор:  Иван Денисов [ Суббота, 07 Март, 2020 20:02 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

Промежуточные вычисления INTEGER компилятор размещает в INTEGER. Ну и только в финале переводит к типу LONGINT.

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

Вот так:
Код:
total := LONG(block) * LONG(sector) * LONG(number);

Автор:  Иван Денисов [ Суббота, 07 Март, 2020 20:09 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

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

Код:
VAR i: INTEGER; b: REAL;
BEGIN
i  := 50;
b := FLT(i) / 5.0;


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

Автор:  olegr [ Суббота, 07 Март, 2020 20:14 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

т.е. внутри ББ при вычислении выражений из INTEGER создается внутренний буфер того же типа?

Автор:  Иван Денисов [ Суббота, 07 Март, 2020 20:17 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

olegr писал(а):
т.е. внутри ББ при вычислении выражений из INTEGER создается внутренний буфер того же типа?

Что-то вроде того. Тут вам компиляторщики лучше ответят, "буфер" там или "стек" или как это правильно называется...

Автор:  olegr [ Суббота, 07 Март, 2020 20:18 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

Спасибо! Все понял.

Автор:  Info21 [ Суббота, 07 Март, 2020 20:24 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

При вычислении с типами не длиннее INTEGER все промежуточные значения -- INTEGER.

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

Хотя для надёжности можно сделать и как посоветовал ИАД.

Автор:  adimetrius [ Суббота, 07 Март, 2020 21:00 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

Иван Денисов писал(а):
В Компонентном Паскале не так строго. Но из-за этого надо держать такие преобразования в голове. Еще и преобразования длинных типов иметь в виду, то с чем вы столкнулись. Но это всё равно намного легче, чем в языках с повсеместным преобразованием всего во всё.


Голова - для других, более приятных и творческих вещей, нехорошо там всякие длинные преобразования держать.
А что если "устрожить" эти правила КП как опцию компилятора? Я у себя по умолчанию включил все проверки диапазонов.

Автор:  Trurl [ Суббота, 07 Март, 2020 21:05 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

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

Автор:  olegr [ Суббота, 07 Март, 2020 21:15 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

adimetrius писал(а):
Голова - для других, более приятных и творческих вещей, нехорошо там всякие длинные преобразования держать.
А что если "устрожить" эти правила КП как опцию компилятора? Я у себя по умолчанию включил все проверки диапазонов.


Как будет выглядеть проверка диапазонов для моего примера?

Автор:  Иван Денисов [ Суббота, 07 Март, 2020 21:18 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

olegr, чтобы во время выполнения программа аварийно остановилась при переполнении и сообщила об ошибке, вы можете вот такой командой компилировать ваш модуль
Код:
DevCompiler.CompileThis Kern+


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

Код:
DevCompiler.CompileOpt('+')


Файлы меню править удобно через меню Info/Menus
UPD2. Убрал неверную картинку.

Автор:  olegr [ Суббота, 07 Март, 2020 21:32 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

Спасибо Иван, жаль нет доки по опциям компилятора ББ в стандартном дистрибутиве.

Автор:  adimetrius [ Суббота, 07 Март, 2020 21:36 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

olegr писал(а):
adimetrius писал(а):
Голова - для других, более приятных и творческих вещей, нехорошо там всякие длинные преобразования держать.
А что если "устрожить" эти правила КП как опцию компилятора? Я у себя по умолчанию включил все проверки диапазонов.


Как будет выглядеть проверка диапазонов для моего примера?


Будет авост. И вы узнаете об ошибке сразу, а не будете гадать - почему это у меня какое-то непонятное значение в LONGINT?

VAR l: LONGINT; x: INTEGER;
BEGIN x := MAX(INTEGER); l := x + 1;

Автор:  Иван Денисов [ Суббота, 07 Март, 2020 21:41 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

olegr писал(а):
Спасибо Иван, жаль нет доки по опциям компилятора ББ в стандартном дистрибутиве.

Это есть в стандартном дистрибутиве, в документе P-S-I (Platform-Specific Issues).

Вот так будет правильно в меню. Выше без проверки опубликовал. Теперь проверил.
DevCompiler.CompileOpt('+') не включает опцию, а именно компилирует оказывается.

Код:
   SEPARATOR
   "#Dev:&Compile"   "K"   "DevCompiler.CompileOpt('+')"   "TextCmds.FocusGuard"
   "#Dev:&Compile And Unload"   ""   "DevCompiler.CompileOpt('+'); DevDebug.Unload"   "TextCmds.FocusGuard"

Автор:  olegr [ Суббота, 07 Март, 2020 21:51 ]
Заголовок сообщения:  Re: LONGINT => INTEGER

Да теперь вижу, есть. Там еще не читал…

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/