OberonCore
https://forum.oberoncore.ru/

Битовая арифметика
https://forum.oberoncore.ru/viewtopic.php?f=29&t=2466
Страница 1 из 1

Автор:  Роман М. [ Воскресенье, 21 Март, 2010 17:26 ]
Заголовок сообщения:  Битовая арифметика

Есть два варианта процедур, возвращающих младшее слово от двойного слова. Но одна из них сбоит, а другая - нет, хотя разницы не вижу.
Код:
(*   (* рабочая версия *)
   PROCEDURE IntLow (a: LONGINT): INTEGER;
      VAR x: LONGINT;
   BEGIN
      x := a MOD 100000000L;
      RETURN SHORT(x)
   END IntLow;*)

   (* НЕрабочая версия *)
   PROCEDURE IntLow (a: LONGINT): INTEGER;
   BEGIN
      RETURN SHORT(a MOD 100000000L)
   END IntLow;

   PROCEDURE Test*;
      VAR y, z: LONGINT; x: INTEGER;
   BEGIN
      (* TEST PASSED *)
      z := 7FFFFFFF7FFFFFFFL; (* MAX(LONGINT) - MAX(INTEGER) - 1 *)
      x := IntLow(z);
      
      (* TEST FAILED *)
      z := 7FFFFFFF80000000L; (* MAX(LONGINT) - MAX(INTEGER) *)
      x := IntLow(z);
   END Test;

Автор:  Валерий Лаптев [ Воскресенье, 21 Март, 2010 17:56 ]
Заголовок сообщения:  Re: Битовая арифметика

Дык может быть дело как раз в присваивании?
Код:
SHORT(a MOD 100000000L)

не эквивалентно ?
Код:
x:= a MOD 100000000L;
SHORT(x)

Автор:  Роман М. [ Воскресенье, 21 Март, 2010 18:04 ]
Заголовок сообщения:  Re: Битовая арифметика

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

Автор:  Александр Шостак [ Воскресенье, 21 Март, 2010 18:08 ]
Заголовок сообщения:  Re: Битовая арифметика

Такое ощущение, что RETURN сразу задаёт диапазон значений в соответствии с типом, возвращаемый процедурой (INTEGER). Тогда SHORT(подвыражение) фактически уже принимает аргумент INTEGER.

Автор:  Comdiv [ Воскресенье, 21 Март, 2010 18:26 ]
Заголовок сообщения:  Re: Битовая арифметика

Вообще, выпадать они должны в обоих случаях, поскольку результатом SHORT(number) должен быть тождество number, что для 80000000L невозможно (это больше чем MAX(INTEGER)). То, что первый вариант работает и возвращает отрицательное число, это лишь особенность реализации, на которую уповать не стоит.

Автор:  Александр Шостак [ Воскресенье, 21 Март, 2010 18:53 ]
Заголовок сообщения:  Re: Битовая арифметика

В таком случае нужно реализовывать её через SYSTEM и ассемблеровский код.
Что-то вроде POP EAX; POP EAX; RET; $58 $58 $C3

Автор:  Валерий Лаптев [ Воскресенье, 21 Март, 2010 20:27 ]
Заголовок сообщения:  Re: Битовая арифметика

Роман М. писал(а):
Эквивалентны они с теоретической стороны, а на практике, как видно, не эквивалентны.
Возможно, где-то отсутствуют требуемые проверки. Я что-то не хочу лезть в код ББ для выяснения.

Скорее всего дело в размерах промежуточных переменных. В присваивании вы явно задаете тип промежуточной переменной как длинный. А неявно, видимо, размер равен обычному целому.

Автор:  Александр Шостак [ Воскресенье, 21 Март, 2010 20:44 ]
Заголовок сообщения:  Re: Битовая арифметика

В арифметических операциях размер устанавливает тип с большим диапазоном. INT + LONGINT = LONGINT

Автор:  AVC [ Воскресенье, 21 Март, 2010 21:37 ]
Заголовок сообщения:  Re: Битовая арифметика

Любопытен "заголовок" трапа:
undefined real result (B9A3, 37E)
Такое впечатление, что в операции 7FFFFFFF80000000H MOD 100000000L как-то используется плавающая арифметика.
Обратите внимание на "экспоненту" числа 7FFFFFFF80000000H.

Автор:  Info21 [ Воскресенье, 21 Март, 2010 22:02 ]
Заголовок сообщения:  Re: Битовая арифметика

AVC писал(а):
Любопытен "заголовок" трапа:
undefined real result (B9A3, 37E)
Такое впечатление, что в операции 7FFFFFFF80000000H MOD 100000000L как-то используется плавающая арифметика.
Так оно и есть.

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