Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Несоответствие результатов операции модуля в Free Pascal и ожидаемом поведении

Delphi , Компоненты и Классы , Процедуры и функции

 

Оператор модуля (mod) в Free Pascal может давать результаты, которые отличаются от ожидаемых. Это можно продемонстрировать с помощью программы на Free Pascal, которая выдает результат, не совпадающий с тем же расчетом в Python или Google.

Пример программы на Free Pascal:

program test(output);

var
    a, b, c: longint;

begin
    a := -1282397916;
    b := 2147483647;
    c := a mod b;
    writeln (c:16);
end.

Вывод программы: -1282397916

Теперь сравните это с выводом скрипта на Python:

#!/usr/bin/python

a = -1282397916
b = 2147483647
c = a % b
print (c)

Вывод: 865085731

Этот результат совпадает с результатом, полученным при введении следующего текста в Google или при использовании оператора mod в VAX-Pascal:

(-1282397916 % 2147483647)

Почему Free Pascal работает по-другому?

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

В Паскале используется определение оператора модуля, похожее на определение из евклидовой геометрии. В ISO стандарте 7185 ("Standard Pascal"), страница 48, это определено следующим образом:

  • Операция вида i mod j является ошибкой, если j меньше или равно нулю; в противном случае значение i mod j равно значению (i - (k × j)) для целого k, такое что 0 ≤ i mod j < j.

В других словах: - Оценка выражения вида x mod y является ошибкой, если y меньше или равно нулю; в противном случае существует целое k, такое что x mod y удовлетворяет следующему соотношению: 0 <= x mod y = x − k * y < y.

Таким образом, результат оператора модуля гарантированно будет неотрицательным. Однако, как вы уже заметили, компилятор Free Pascal не придерживается ISO стандартов. FPC будет возвращать правильный результат только если установлен флаг {$modeSwitch isoMod+}:

program moduloConfusion(output);
    {$modeSwitch isoMod+}
    type
        integer = ALUSInt;
    var
        dividend, divisor: integer;
    begin
        dividend := -1282397916;
        divisor  :=  2147483647;
        writeLn(dividend mod divisor:16)
    end.

Обратите внимание, что этот флаг влияет на определение оператора модуля в каждом модуле компиляции, поэтому RTL и все остальное, за исключением перекомпиляции, продолжает использовать другое определение внутри.

Убедитесь, что Delphi и GPC (GNU Pascal Compiler) работают правильно без необходимости прыгать через уловки.

Если вы хотите получить тот же результат, что и в Python, вам нужно определить и использовать свою собственную функцию (в данном случае в расширенном Паскале):

function modulo(dividend, divisor: integer): integer;
begin
    modulo := (abs(dividend) mod abs(divisor)) * -1 pow ord(divisor < 0)
end;

К сожалению, нет магического переключателя, чтобы заставить Free Pascal's mod работать точно так же, как Python's %.

Альтернативное решение

Для получения поведения, которое совпадает с Python, можно использовать следующий подход:

  1. Функция с использованием условий:
function modulo(dividend, divisor: integer): integer;
begin
    if divisor < 0 then
        modulo := -(abs(dividend) mod abs(divisor))
    else
        modulo := dividend mod divisor;
end;

Этот подход учитывает знак делителя и корректирует результат в зависимости от него, чтобы он соответствовал поведению Python.

  1. Использование библиотеки для расширения функциональности:

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

Заключение

Различия в поведении оператора модуля между Free Pascal и Python обусловлены различиями в стандартах, которые используются этими языками. Если вам нужно получить поведение, совместимое с Python, можно использовать один из предложенных выше подходов. Это позволит вам избежать неожиданных результатов и обеспечит согласованность поведения ваших программ на разных языках программирования.

Создано по материалам из источника по ссылке.

Context — это материал, который объясняет различие в поведении оператора модуля между Free Pascal и Python, а также предлагает методы для достижения поведения, совместимого с Python, в Free Pascal.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Процедуры и функции ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-03-22 17:56:31/0.0035829544067383/0