Пакетна операція повертає "Поділити на нульову помилку" із затримкою розширення та дійсною операцією


0

Наступний рядок коду проходить через мій поточний проект:

set /a "hp = hp - ((atk*arandom)/((edef*6)/edefbonus))"

Ось як це виглядає, коли ви замінюєте змінні на їх значення:

set /a "hp = 50 - ((2*2)/((1*6)/8))"

Відповідь на це - 44.666667, що має бути округлено до 45. Але замість цього Batch просто каже мені "Поділити на нульову помилку", коли код працює, як з версією, яка використовує змінні, так і з версією, яка замість цього використовує числа.

Я справді програв за доказів. Я перевірив наявність нерівномірних дужок, перевірив наявність не змінених змінних та встановлено EnabledDelayedExpansion. Так що я роблю неправильно ...?

Відповіді:


2

Якщо немає причини для ділення знаменника на edfbonus, а не множення чисельника на нього, ви можете уникнути проблеми з нульовим дільником, переставивши обчислення:

set /a "hp = hp - ((atk*arandom*edefbonus)/(edef*6))"

Зовнішні дужки та лапки є непотрібними, а set / a має оператора, який зберігає деякі вводити та виправляє такі вирази:

set /a hp -= atk*arandom*edefbonus/(edef*6)

Оскільки ви згадали про округлення, я додам це:

Якщо значення праворуч від -=оператора вище завжди позитивне, найпростіший спосіб зробити округлення:

set /a hp -= (10*atk*arandom*edefbonus/(edef*6)+5)/10

Зауважте, що ми множимо на 10 перед діленням, а не після нього, тому обчислення йде:

10*2*2*8 =320
1*6      =6
320/6    =53
53+5     =58
58/10    =5

Якщо ми помножили на 10 після ділення, як у

set /a hp -= (atk*arandom*edefbonus/(edef*6)*10+5)/10,

розрахунок піде:

2*2*8 =32
1*6   =6
32/6  =5   (we just lost the fraction digit, so rounding won't work)
5*10  =50
50+5  =55
55/10 =5

Той самий результат, але тільки тому, що округлення все-таки було б округлене вниз.


1

Пакет не може обробляти числа з плаваючою комою, лише цілі числа.

Так ((1*6)/8)= 0замість 0.75. Потім ви намагаєтесь поділити (2*2)на це 0, даючи помилку "Поділити на нуль".

Пропоноване рішення? Замість цього використовуйте PowerShell:

PS Y:\> $hp = 50 - ((2*2)/((1*6)/8))
PS Y:\> $hp
44.6666666666667

Супутнє питання SU:

Пов'язане питання ТА:


1

Пакетна операція повертає "Поділити на нульову помилку"

set /a "hp = 50 - ((2*2)/((1*6)/8))"

Це тому, що 1*6= 6і 6/8= 0.75.

І:

Будь-який SET / Обчислення, який повертає результат дробу, буде округлений до найближчого цілого числа.

Так 0.75округляється до 0.

6/0 повертає "Поділити на нульову помилку".


Обхідні шляхи

Немає реальних обхідних шляхів, які дозволяють математику з плаваючою комою, за винятком використання інших мов сценарію.

Єдиним винятком може бути, якщо у вас обмежена і фіксована кількість десяткових знаків (наприклад, 2), ви можете просто помножити все на 100.

Щоб відобразити десятковий роздільник у кінцевих результатах, об'єднайте ціле ділення на 100, а потім - десятковий роздільник, після чого ділимо модуль на 100:

SET Whole = Result / 100
SET "Fraction = Result %% 100"
SET Result=%Whole%.%Fraction%

Однак це може зламатися на 32-бітному обмеженні.

Загалом, для математики з плаваючою комою я рекомендував би використовувати інші мови сценаріїв.

Джерело Math у пакетних файлах NT


Арифметичні вирази (SET / a)

Розміщення виразів у "лапках" необов'язково для простої арифметики, але необхідне для будь-якого виразу за допомогою логічних операторів.

Будь-який SET / Обчислення, який повертає результат дробу, буде округлений до найближчого цілого числа.

Набір джерела


Подальше читання

  • Індекс AZ командного рядка Windows CMD - відмінна довідка для всіх речей, що стосуються cmd-рядка Windows.
  • set - відображення, встановлення або видалення змінних середовища CMD. Зміни, внесені за допомогою SET, залишаться лише протягом тривалого сеансу CMD.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.