Como posso calcular divisão e módulo para inteiros em C #?

87

Como posso calcular a divisão e o módulo para números inteiros em C #?

kartal
fonte
16
Isso pode ser muito básico, mas é uma questão real ...
2
Um relacionado pós e uma leitura obrigatória blogue sobre o porquê de %operador é não o operador módulo em C #.
RBT

Respostas:

124

Antes de fazer perguntas desse tipo, verifique a documentação do MSDN .

Quando você divide dois inteiros, o resultado é sempre um inteiro. Por exemplo, o resultado de 7/3 é 2. Para determinar o restante de 7/3, use o operador de resto ( % ).

int a = 5;
int b = 3;

int div = a / b; //quotient is 1
int mod = a % b; //remainder is 2
as-cii
fonte
10
% retorna o resto, não o módulo (como você indicou). Eles não são a mesma coisa e podem causar problemas ao lidar com casos incomuns (por exemplo, índices negativos). No entanto, ele pode ser usado como o operador de módulo quando apenas procurando, por exemplo, a cada 10 iterações de um indexador fracamente positivo. Talvez você possa explicar como calcular o módulo real?
Cor_Blimey
1
É verdade, eu li postagens como esta e tive problemas em meu aplicativo :)
apocalipse
1
... Qual é exatamente o sentido de declarar ae bse você não vai usá-los? : D
leviathanbadger
1
Talvez o usuário estivesse procurando (como eu) por uma função DivRem, então a questão pode não ser tão trivial quanto parece à primeira vista. Obrigado @danodonovan
Tancredi
1
A resposta não é tão simples quanto afirma esta resposta, como outros também apontaram, e pode levar a erros difíceis de depurar. Consulte /programming/10065080/mod-explanation
SansWit de
90

Também há Math.DivRem

quotient = Math.DivRem(dividend, divisor, out remainder);
danodonovan
fonte
2
Esta deve ser a resposta correta em minha opinião, porque fornece o quociente E o resto em uma função. Não tenho certeza de qual abordagem tem melhor desempenho (usando "a / b" para obter o quociente e "a% b" para obter o resto ou Math.DivRem), mas essa abordagem certamente é muito mais agradável de ler (no meu caso, preciso saber o quociente e o restante) - obrigado!
Igor
2
@Igor obrigado, quando a pergunta original foi respondida esta função não existia! No entanto, a existência da função faz com que o comentário do as-cii sobre a verificação da documentação pareça um pouco bobo .... :)
danodonovan
6
Apenas para evitar confusão, Math.DivRemnão calcula div e mod em uma operação. É apenas uma função auxiliar e seu código fonte é exatamente: public static int DivRem(int a, int b, out int result) { result = a%b; return a/b; }.
NightElfik
9
@NightElfik A implementação pode mudar no futuro, e é mais fácil para o tempo de execução identificar uma chamada de método para otimização do que disjunta dive reminstruções
kbolino
6
@kbolino Isso é uma grande previsão, uma vez que tenha mudado , pelo menos em .NET Core, dividir e subtrair. E há mais otimizações planejadas no RyuJIT para usar uma única instrução x86 div, embora reconheço que as alterações JIT também devem detectar os operadores %e /se usadas individualmente.
Bob
15

Fato engraçado!

A operação de 'módulo' é definida como:

a % n ==> a - (a/n) * n

Ref: Aritmética Modular

Portanto, você pode lançar o seu próprio, embora seja MUITO mais lento do que o operador% integrado:

public static int Mod(int a, int n)
{
    return a - (int)((double)a / n) * n;
}

Edit: uau, falei mal aqui originalmente, obrigado @joren por me pegar

Agora estou contando com o fato de que division + cast-to-int em C # é equivalente a Math.Floor(isto é, elimina a fração), mas uma implementação "verdadeira" seria algo como:

public static int Mod(int a, int n)
{
    return a - (int)Math.Floor((double)a / n) * n;
}

Na verdade, você pode ver as diferenças entre% e "módulo verdadeiro" com o seguinte:

var modTest =
    from a in Enumerable.Range(-3, 6)
    from b in Enumerable.Range(-3, 6)
    where b != 0
    let op = (a % b)
    let mod = Mod(a,b)
    let areSame = op == mod
    select new 
    { 
        A = a,
        B = b,
        Operator = op, 
        Mod = mod, 
        Same = areSame
    };
Console.WriteLine("A      B     A%B   Mod(A,B)   Equal?");
Console.WriteLine("-----------------------------------");
foreach (var result in modTest)
{
    Console.WriteLine(
        "{0,-3} | {1,-3} | {2,-5} | {3,-10} | {4,-6}", 
        result.A,
        result.B,
        result.Operator, 
        result.Mod, 
        result.Same);
}

Resultados:

A      B     A%B   Mod(A,B)   Equal?
-----------------------------------
-3  | -3  | 0     | 0          | True  
-3  | -2  | -1    | -1         | True  
-3  | -1  | 0     | 0          | True  
-3  | 1   | 0     | 0          | True  
-3  | 2   | -1    | 1          | False 
-2  | -3  | -2    | -2         | True  
-2  | -2  | 0     | 0          | True  
-2  | -1  | 0     | 0          | True  
-2  | 1   | 0     | 0          | True  
-2  | 2   | 0     | 0          | True  
-1  | -3  | -1    | -1         | True  
-1  | -2  | -1    | -1         | True  
-1  | -1  | 0     | 0          | True  
-1  | 1   | 0     | 0          | True  
-1  | 2   | -1    | 1          | False 
0   | -3  | 0     | 0          | True  
0   | -2  | 0     | 0          | True  
0   | -1  | 0     | 0          | True  
0   | 1   | 0     | 0          | True  
0   | 2   | 0     | 0          | True  
1   | -3  | 1     | -2         | False 
1   | -2  | 1     | -1         | False 
1   | -1  | 0     | 0          | True  
1   | 1   | 0     | 0          | True  
1   | 2   | 1     | 1          | True  
2   | -3  | 2     | -1         | False 
2   | -2  | 0     | 0          | True  
2   | -1  | 0     | 0          | True  
2   | 1   | 0     | 0          | True  
2   | 2   | 0     | 0          | True  
JerKimball
fonte
"Agora estou contando com o fato de que a divisão inteira em C # é equivalente a Math.Floor (ou seja, elimina a fração)" - Mas não é. A divisão inteira gira em direção a zero, Math.Floor gira em direção ao infinito negativo.
Joren
@Joren Desculpe, mas não - tente executar isto: Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x));- todos os 0
JerKimball
2
Em primeiro lugar, estou falando sobre divisão inteira . O que acontece se você fizer uma divisão de ponto flutuante e, em seguida, converter para inteiro é irrelevante (embora forneça o mesmo resultado). Em segundo lugar, não sei por que você esperaria que inteiros entre 0 e 9 fornecessem qualquer coisa diferente de 0 depois de dividir por 10 e truncar para a parte inteira. Se isso resultou em 1 que seriam arredondamento longe de zero ou em direção positiva infinito. Terceiro, não há nenhuma diferença entre arredondar para zero e arredondar para infinito negativo para números positivos, portanto, você nem mesmo está abordando o problema.
Joren
Math.Floor(-10.0 / 3.0)e não-10 / 3 são a mesma coisa.
Joren
@joren ah, vejo a desconexão aqui - não, não estou executando a divisão inteira , estou executando a divisão dupla e, em seguida, convertendo o resultado para um número inteiro - muito diferente.
JerKimball
14

A divisão é realizada usando o /operador:

result = a / b;

A divisão do módulo é feita usando o %operador:

result = a % b;
Rion Williams
fonte
1
+1: Convenientemente, omitir o tipo torna a resposta melhor :-) Eu acredito que isso funciona com System.Numeric.BigInteger no 4.0 também.
5
% -> como Cor_Blimey disse, ele retorna o resto, não o módulo. Por exemplo: (-5% 3) == -2 [C #], -5 mod 3 = 1 [wolframalpha.com].
apocalipse de
2
Nota: Módulo não é igual a Módulo. Módulo é o resto, Módulo é o valor absoluto.
Ryan
-4

Leia dois inteiros do usuário. Em seguida, calcule / exiba o restante e o quociente,

// When the larger integer is divided by the smaller integer
Console.WriteLine("Enter integer 1 please :");
double a5 = double.Parse(Console.ReadLine());
Console.WriteLine("Enter integer 2 please :");
double b5 = double.Parse(Console.ReadLine());

double div = a5 / b5;
Console.WriteLine(div);

double mod = a5 % b5;
Console.WriteLine(mod);

Console.ReadLine();
James Dombroski
fonte