Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 18 июн 2025, 01:37

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
СообщениеДобавлено: 16 сен 2018, 14:02 
Не в сети

Сообщения: 116
Откуда: Каменск-Уральский
Я написал небольшую процедурку, но почему-то она выдаёт отрицательное число в самом конце: при умножении трёх положительных чисел. Может только у меня такой глюк?
Код: "OBERON"
  1. IMPORT StdLog, WinApi;
  2.  
  3. PROCEDURE Start*;(**)
  4. VAR bool: INTEGER;
  5. i1, i2, i3, i4: INTEGER;
  6. BEGIN
  7. StdLog.String(" съёмный диск; i1: ");
  8. bool := WinApi.GetDiskFreeSpace("c:", i1, i2, i3, i4);
  9. StdLog.Int(i1);
  10. StdLog.Ln;
  11. StdLog.String ("i2: ");
  12. StdLog.Int(i2);
  13. StdLog.Ln;
  14. StdLog.String ("i3: ");
  15. StdLog.Int(i3);
  16. StdLog.Ln;
  17. StdLog.String ("i4: ");
  18. StdLog.Int(i4);
  19. StdLog.Ln;
  20. StdLog.String ("bool: ");
  21. StdLog.Int(bool);
  22. StdLog.Ln;
  23. StdLog.Int(16 * 512 *i3)
  24. END Start;
  25.  


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 16 сен 2018, 22:36 
Не в сети

Сообщения: 146
Перед тем как ответить напрямую, предлагаю провести эксперимент. Если бы приложение завершилось аварийно с выведением сообщения такого рода
Код: "OBERON"
  1. mul: Assertion `!overflow' failed
Вы бы поняли в чём проблема?


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 сен 2018, 02:41 
Не в сети

Сообщения: 116
Откуда: Каменск-Уральский
Т.к. overflow переводится как переполнение, то вы имеете в виду, что я отправил в процедуру StdLog.Int слишком большое значение? Но как тогда выполняется StdLog.Int(MAX(LONGINT))?


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 сен 2018, 14:18 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
MAX(INTEGER) = 2147483647
16 * 512 * 2061913 = 16891191296

Соответственно, мы должны явно указать компилятору о нашем желании произвести вычисления в длинном типе LONGINT:
Код: "OBERON"
  1. StdLog.Int(16 * 512 * LONG(i3));
(приводим к LONGINT один операнд, и компилятор уже не понижает мощность типа, чтобы не потерять разряды)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 сен 2018, 14:32 
Не в сети

Сообщения: 116
Откуда: Каменск-Уральский
Скажите, а почему компилятор понижает разряды, если написать так:
Код: "OBERON"
  1. i5: LONGINT;
  2. i5 := 16 * 512 * i3;
  3. StdLog.Int(i5);
?
Как-то странно: если числа ввести константами, то не понижает...


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 сен 2018, 14:52 
Не в сети

Сообщения: 116
Откуда: Каменск-Уральский
Совсем забыл: Паскалю вообще не свойственно автоматическое приведение типов.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 сен 2018, 16:21 
Не в сети

Сообщения: 146
Всё не так. Никто ничего не понижает. Переполнение происходит во время умножения(mul в гипотетическом сообщении), так как значения вычисляются в типе INTEGER. Log.Int принимает параметр типа LONGINT, поэтому он и может принять значение INTEGER, но оно уже искажено переполнением. Значение перемноженных констант, сразу идёт в типе LONGINT, потому что компилятор знает, что получаемое значение не помещается в диапазон INTEGER.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 17 сен 2018, 16:35 
Не в сети

Сообщения: 146
Документация к StdLog, кстати, вводит в заблуждение. Думаю, это скоро поправят
Цитата:
PROCEDURE Int (i: INTEGER)
Writes an integer value to the log.
Код: "OBERON"
  1. PROCEDURE Int* (i: LONGINT);
  2. BEGIN
  3. out.WriteChar(" "); out.WriteInt(i); Flush
  4. END Int;


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 18 сен 2018, 18:30 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Len писал(а):
Скажите, а почему компилятор понижает разряды, если написать так:
Код: "OBERON"
  1. i5: LONGINT;
  2. i5 := 16 * 512 * i3;
  3. StdLog.Int(i5);
?
Как-то странно: если числа ввести константами, то не понижает...
Len, достаточно знать, что в языке КП по умолчанию целочисленная арифметика является 32-битной (тип INTEGER). Всегда. Кроме тех случаев, когда явно указать компилятору, что нужно перейти к LONGINT.

В выражении i5 := 16 * 512 * i3 переменная i5 конечно типа LONGINT, но такая переменная принимает результат вычислений типа INTEGER тоже. Что и имеет место в данном случае.

Приводить константу 16 или 512 к LONGINT нет смысла. Надо приводить переменную i3, притом _перед_ вычислением, а не после него. И тогда компилятор будет работать в диапазоне уже не INTEGER, как это он делает по умолчанию, а LONGINT, как указал ему программист. Вроде всё просто. У меня с этим никогда не было проблем.


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 2 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 24


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
© VEDAsoft Oberon Club