A operação em lote retorna "Dividir por erro zero" com a expansão atrasada em uma operação válida

0

A seguinte linha de código é executada através do meu projeto atual:

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

E aqui está o que parece quando você substitui as variáveis por seus valores:

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

A resposta para isso é 44.666667, que deve ser arredondada para 45. Mas em vez disso, o Batch apenas me diz "Divide by zero error" quando o código é executado, ambos com a versão que usa as variáveis e com a versão que usa números em vez de.

Estou realmente perdido por pistas. Verifiquei parênteses irregulares, verifiquei se há variáveis não definidas e EnabledDelayedExpansion está definido. Então, o que estou fazendo errado ...?

    
por Mathys Oliveira 19.04.2016 / 17:31

3 respostas

2

A menos que haja uma razão para dividir o denominador por edfbonus em vez de multiplicar o numerador por ele, é possível evitar o problema do divisor zero reorganizando o cálculo:

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

Os parênteses externos e as aspas são desnecessários, e set / a tem um operador que economiza digitação e organiza expressões como esta:

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

Como você mencionou o arredondamento, adicionarei isso:

Contanto que o valor à direita do operador -= acima seja sempre positivo, a maneira mais simples de fazer o arredondamento é:

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

Observe que multiplicamos por 10 antes da divisão, não depois dela, então o cálculo é:

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

Se multiplicarmos por 10 após a divisão, como em

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

o cálculo seria:

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

O mesmo resultado, mas apenas porque o arredondamento seria arredondado para baixo de qualquer maneira.

    
por 19.10.2017 / 00:02
1

O lote não pode lidar com números de ponto flutuante, apenas inteiros.

Então ((1*6)/8) = 0 em vez de 0.75 . Você então tenta dividir (2*2) por esse 0 , dando a você um erro "Dividir por zero".

Solução sugerida? Use o PowerShell:

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

Pergunta sobre SU relacionada:

Relacionada com a pergunta SO:

por 19.04.2016 / 17:44
1

A operação em lote retorna "Dividir por erro zero"

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

Isso ocorre porque 1*6 = 6 e 6/8 = 0.75 .

E:

Any SET /A calculation that returns a fractional result will be rounded down to the nearest whole integer.

Portanto, 0.75 é arredondado para 0 .

6/0 retorna "Dividir por erro zero".

Soluções alternativas

There are no real workarounds that allow floating point math, except using other scripting languages.

The only exception may be if you have a limited and fixed number of decimals (e.g. 2), then you can just multiply everything by 100.

To display a decimal delimiter in the end results, concatenate the integer divide by 100, followed by the decimal delimiter, followed by the modulo divide by 100:

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

This may break on the 32-bit limit, though.

In general, for floating point math I would recommend using other scripting languages.

Fonte Matemática em arquivos em lote do NT

Expressões aritméticas (SET / a)

Placing expressions in "quotes" is optional for simple arithmetic but required for any expression using logical operators.

Any SET /A calculation that returns a fractional result will be rounded down to the nearest whole integer.

Fonte conjunto

Leitura Adicional

  • Um índice A-Z da linha de comando do Windows CMD - Uma excelente referência para todas as coisas relacionadas à linha do Windows cmd.
  • definir - Exibir, definir ou remover variáveis de ambiente do CMD. As alterações feitas com o SET permanecerão apenas pela duração da sessão atual do CMD.
por 19.04.2016 / 17:45