Ограничение 32-битного целого числа в пакетных скриптах

Вопрос или проблема

Можно ли как-то преодолеть ограничение в 32 бита для операций с целыми числами в Batch. Я выполняю некоторые операции сложения в своем скрипте, и сумма превышает диапазон (2^31 -1).

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

Источник Математика в NT batch файлах

Обходные пути: 32-бит

Обходные пути для ограничения 32-бит включают:

  1. деление на 1000 (или любую степень 10) за счет отсечения последних (3) цифр

  2. разделение чисел на отдельные десятичные цифры и выполнение всех арифметических операций и логики переноса “вручную”

  3. другие скриптовые языки

Обходной путь №1 можно использовать для сложения, к примеру, дискового пространства:

Пример кода “Chop”

Секрет в том, что каждое (большое) число обрабатывается как строка, затем справа отсекаются 6 символов (цифр), и только потом результат обрабатывается как число.

Это довольно грубый обходной путь, так как он “округляет” все числа перед проведением арифметики. Однако добавление половины мегабайта для каждого подкаталога (%Count% / 2) к %Total% компенсирует эти усечения, так что полный итог становится более точным, чем отдельные числа. Обратите внимание, что числа не представляют “настоящие” мегабайты (1024 x 1024), а скорее миллион байт (1000 x 1000).

Обходной путь №2 идеально демонстрирует пакетные файлы Брайана Уильямса:

Add.bat

IsLarger.cmd

Multiply.cmd

Идеально, но довольно сложно.

Обходной путь №3, другие скриптовые языки, говорит сам за себя.

Обходные пути: целые числа

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

Единственное исключение может быть, если у вас ограниченное и фиксированное количество десятичных знаков (например, 2), тогда вы можете просто умножить все на 100.

Чтобы отображать десятичный разделитель в конечных результатах, объединив целочисленное деление на 100 с десятичным разделителем и затем с модульным делением на 100:

SET Whole = Result / 100 SET “Fraction = Result %% 100” SET Result=%Whole%.%Fraction%

Однако это может нарушиться на 32-битном пределе.

В общем, для математики с плавающей запятой я бы рекомендовал использовать другие скриптовые языки.

Для этого случая необходимы внешние инструменты. В качестве отправной точки можно использовать bc (поддерживает произвольную точность и предустановлен на большинстве систем Linux):

echo ‘123456789*123456789’ | bc

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

{
1,000,000,000 кредит A
+2,000,000,000 кредит B

3,000,000,000 (промежуточный результат превышает предел 2,147,483,647)
  • 900,000,000 дебет C

2,100,000,000 (промежуточный результат в порядке)
  • 900,000,000 дебет D

1,200,000,000 ОКОНЧАТЕЛЬНЫЙ БАЛАНС (результат в порядке)

}

Если вы отсортируете числа по абсолютному значению и правильно организуете сложение и вычитание, вы можете избежать превышения предела:

{
2,000,000,000 кредит B

  • 900,000,000 дебет C

1,100,000,000 (промежуточный в порядке)
+1,000,000,000 кредит A

2,100,000,000 (промежуточный в порядке)

  • 900,000,000 дебет D

1,200,000,000 ОКОНЧАТЕЛЬНЫЙ БАЛАНС
}

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

Ответ или решение

Иногда в процессе работы с пакетными файлами на Windows мы сталкиваемся с ограничениями, возникающими из-за специфики их реализации. Одним из таких ограничений является использование 32-битной арифметики, что ограничивает допустимый диапазон целых чисел в пакетных скриптах до значения (2^{31} – 1), что эквивалентно 2,147,483,647. Это может стать проблемой при выполнении арифметических операций, где результат превышает указанный предел. Рассмотрим, как можно обойти это ограничение.

Теория: Ограничения 32-битной арифметики в Batch Script

Пакетные файлы (Batch Scripts) предназначены для автоматизации задач в операционной системе Windows и основаны на языке командной строки. В их основе лежит использование 32-битной арифметики, что означает, что любые операции над целыми числами ограничены максимальным значением 2,147,483,647. Это может стать непреодолимым препятствием в случаях, когда вы работаете с большими числами, например, при сложении, умножении или других интенсивных вычислительных задачах.

Пример: Способы обхода ограничения

Существуют несколько методов для обхода ограничений, связанных с использованием 32-битных целых чисел в пакетных скриптах:

  1. Метод деления и округления: Один из простейших способов справиться с проблемой – использовать деление чисел на степени десяти и повторное умножение после выполнения операций. Например, при сложении больших чисел, можно "отсечь" последние несколько цифр, затем сложить и вернуть числам их исходный масштаб. Это довольно грубый метод, который работает в случаях, когда допустима потеря точности.

  2. Работа с цифрами поразрядно: Другим методом является разбивка чисел на отдельные десятичные разряды и проведение всех математических операций "вручную". Это сложный и трудозатратный подход, который требует детальной проработки логики переноса и округления.

  3. Использование других языков скриптов: Самым эффективным подходом будет использование других языков программирования или скриптов, которые поддерживают большие числа или плавающую запятую. Например, использовать VBScript или JScript для выполнения сложных математических операций.

Применение: Реализация в реальном сценарии

Для того чтобы реализовать обход 32-битных ограничений на практике, вы можете интегрировать решения из сторонних языков в свой пакетный скрипт. Вот пример, как это можно сделать, используя JavaScript внутри командного скрипта:

@echo off
setlocal EnableDelayedExpansion

rem Передаем аргументы в JScript
set "a=2147483647"
set "b=123456789"

rem Используем JScript для выполнения арифметических операций
cscript //nologo //e:javascript "%~f0?.wsf" %a% %b%

:end
exit /b

<job>
    <script language="JScript">
        // Получаем аргументы из командной строки
        var a = WScript.Arguments(0);
        var b = WScript.Arguments(1);

        // Преобразуем в числа и складываем
        var result = parseInt(a) + parseInt(b);

        // Выводим результат
        WScript.Echo("Result: " + result);
    </script>
</job>

Этот пример показывает, как скрипт на JavaScript может быть встроен в пакетный файл, предоставляя возможность работать с большими числами и избегать ограничений 32-битной арифметики. Подобные интеграции открывают дополнительные возможности для обработки данных и выполнения сложных вычислений, что расширяет функциональность традиционных пакетных файлов.

Подводя итог, следует отметить, что выбор метода обхода вышеописанных ограничений зависит от конкретного сценария и требований к точности вычислений. Использование других языков программирования в конечном итоге представляется наиболее гибким и мощным решением, которое позволяет существенно расширить возможности стандартных средств Windows для автоматизации задач.

Оцените материал
Добавить комментарий

Капча загружается...