inteiro

inteiro

Se a escala for diferente de zero, cálculos com %, como 3%2 e 46%4, tendem a gerar 0. Como o algoritmo é projetado com uma escala diferente de 0?

bc
scale=10
print 4%3   // output 0

Responder1

Omanual de comandodiz o seguinte sobre como BC calcula o módulo:

O resultado da expressão é o “resto” e é calculado da seguinte forma. Para calcular a%b, primeiroa/bé calculado para escalar dígitos. Esse resultado é usado para calcularuma - (uma/b) * bà escala do máximo de escala+escala(b) e escala(a).Se a escala for definida como zero e ambas as expressões forem números inteiros, esta expressão será a função de resto inteiro.


EDITAR: Examinei o código-fonte do GNU BC e descobri que o operador mod estende o operador de divisão. Em outras palavras, o módulo é calculado como subproduto da divisão. Baseia-se na divisão inteira para calcular o módulo. Quando scaleé definido, porém a divisão inteira não ocorre.

Tente isso em BC:

bc
scale = 0
print 5/2

scale = 5
print 5/2

voce deveria pegar:

2        << Integer Division
2.50000  << NOT integer division!

Agora vamos inserir esses números da mesma forma que BC faz. O manual diz que usaa-(a/b)*bcalcular. Vamos inserir nossos dois resultados, aquele resultante da divisão inteira e aquele com valor scalediferente de 0.

a - ( a/b ) * b
5 - ( 2   ) * 2  = 1  << CORRECT!
5 - ( 2.5 ) * 2  = 0  << VERY WRONG!

Sem divisão inteira:

a - ( a/b ) * b == a - (  a  ) == 0

É por isso que a escala deve ser definida como 0 para que o módulo funcione corretamente.
A questão parece surgir do design do BC e de como ele lida com números com uma 'escala'. Para que o módulo funcione corretamenteprecisamos de divisão inteira.

outromuitoferramentas mais avançadasque são gratuitos e de código aberto para essa finalidade, e recomendo que você os use.

Responder2

A resposta do user272970 é ótima. Aqui está um ajuste:

define int(x) { auto oldscale; oldscale=scale; scale=0; x=x/1; scale=oldscale; return( x ); }
define fmod(x,y) { auto oldscale; oldscale=scale; scale=1000; x = x - y * int(x/y); scale=oldscale; return( x ); }

Isso (usando auto oldscale) torna oldscalelocal para a função. Sem isso, configurar oldscalefrom int()fmod() substituirá o oldscaleque está tentando ser salvo fmod(), deixando scaledefinido como 1000 em vez do que você tinha antes de chamar fmod().

Adicionei essas funções ~/.bcrce configurei a BC_ENV_ARGSvariável de ambiente como ~/.bcrc. Isso carregará essas funções toda vez que você executar o bc. Portanto, agora posso executar fmod(x,y)a qualquer momento em bc, sem precisar definir manualmente essas funções todas as vezes.

ps scalede 1000 pode ser um exagero na maioria dos casos

Responder3

Eu resolvi assim:

inteiro

definir int(x) { escala antiga=escala; escala=0; x=x/1; escala=escala antiga; retorno(x); }

módulo

definir mod(x,y) { escala antiga=escala; escala=1000; x = x - y * int(x/y); escala=escala antiga; retorno(x); }

HTH

Responder4

Como outra resposta já disse, é o resultado da definição a%bde as (a-(a/b)*b), avaliada no atual scale. Isso significa que se você quiser que ele atue como um módulo inteiro, você precisará usá-lo com scale=0.

No entanto, discordo que esteja "errado". É uma ferramenta potencialmente útil, especialmente para avaliar erros.

scale=5
1/3
> .33333
1%3
> .00001

O que estamos perdendo se representarmos 7/13como decimal de 4 dígitos .5384?

scale=4
7/13
> .5384
7%13
> .0008

Aparentemente 0.0008/13.

E por último, por não insistir em usar números inteiros, pode ser usado para extrair uma parte de um decimal.

scale=1
123.456/1
> 123.4
123.456%1
> .056

informação relacionada