Respostas:
Para alguns números y
e divisores, x
calcule o quociente ( quotient
) e o restante ( remainder
) como:
var quotient = Math.floor(y/x);
var remainder = y % x;
floor
e o %
conjunto não são consistentes dessa maneira. Use em trunc
vez de floor
(permitindo assim restos negativos) ou subtração para obter o restante ( rem = y - div * x
).
rem
de qualquer maneira, você pode obter o quociente div
mais rápido sem pavimentação: (y - rem) / x
. 2. A propósito, a operação do módulo pela definição recomendada por Donald Knuth (sign-match-divisor, não o restante, isto é, módulo euclidiano, nem o JavaScript sign-match-dividend) é o que podemos codificar em JavaScript como function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.
Não sou especialista em operadores bit a bit, mas aqui está outra maneira de obter o número inteiro:
var num = ~~(a / b);
Isso funcionará corretamente também para números negativos, enquanto Math.floor()
arredondará na direção errada.
Isso parece correto também:
var num = (a / b) >> 0;
a/b | 0
~~int
, int | 0
e int >> 0
não modifica o argumento inicial, mas faz com que o intérprete passe parte integrante para o operador.
floor
dificilmente gira na direção errada, dado o nome - mas não a direção que as pessoas geralmente querem!
a = 12447132275286670000; b = 128
Math.floor(a/b)
-> 97243220900677100
e ~~(a/b)
-> -1231452688
.
~~(5/2) --> 2
como faz (5/2)>>0 --> 2
, mas ~~(5/2) + 1 --> 3
enquanto ~~(5/2)>>0 + 1 --> 1
. ~~
é uma boa escolha porque a precedência é mais apropriada.
Eu fiz alguns testes de velocidade no Firefox.
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
O exposto acima é baseado em 10 milhões de tentativas para cada um.
Conclusão: Use (a/b>>0)
(ou (~~(a/b))
ou (a/b|0)
) para obter um ganho de aproximadamente 20% em eficiência. Lembre-se também de que todos são inconsistentes com Math.floor
quando a/b<0 && a%b!=0
.
Math.floor
e quem sabe quantas outras funções da API, ou aprender sobre o ~
operador (bit a bit) e como as operações bit a bit funcionam em JS e depois entender o efeito do double til?
Math.floor
melhor. E mesmo se não, este é googleable.
ES6 apresenta o novo Math.trunc
método. Isso permite corrigir a resposta do @ MarkElliot para que funcione também com números negativos:
var div = Math.trunc(y/x);
var rem = y % x;
Observe que os Math
métodos têm a vantagem sobre os operadores bit a bit de trabalharem com números acima de 2 31 .
18014398509481984 == 18014398509481985
,.
~~(x/y)
. Precisa suportar números maiores de até 54 bits assinados? Use Math.trunc
se tiver, ou Math.floor
não (corrija os números negativos). Precisa suportar números ainda maiores? Use uma grande biblioteca de números.
divmod
, você pode implementá-lo como tal:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
var remainder = x % y;
return (x - remainder) / y;
Math.trunc
:). Eu verifiquei com 100,3; -100,3; 100, -3 e -100, -3. É claro que passou muito tempo desde que seu comentário e as coisas mudaram.
Eu normalmente uso:
const quotient = (a - a % b) / b;
const remainder = a % b;
Provavelmente não é o mais elegante, mas funciona.
Você pode usar a função parseInt
para obter um resultado truncado.
parseInt(a/b)
Para obter um restante, use o operador mod:
a%b
parseInt tem algumas armadilhas com cordas, para evitar o uso do parâmetro radix com base 10
parseInt("09", 10)
Em alguns casos, a representação em cadeia do número pode ser uma notação científica; nesse caso, parseInt produzirá um resultado errado.
parseInt(100000000000000000000000000000000, 10) // 1e+32
Esta chamada produzirá 1 como resultado.
parseInt
deve ser evitado quando possível. Aqui está o aviso de Douglas Crockford: "Se o primeiro caractere da string for 0, a string será avaliada na base 8 em vez da base 10. Na base 8, 8 e 9 não são dígitos, então parseInt (" 08 ") e parseInt ("09") produzem 0 como resultado. Esse erro causa problemas em programas que analisam datas e horas. Felizmente, parseInt pode usar um parâmetro radix, para que parseInt ("08", 10) produz 8. Recomendamos que você sempre forneça o parâmetro radix ". archive.oreilly.com/pub/a/javascript/excerpts/…
parseInt
deve ser evitado; apenas que existem algumas dicas para estar ciente. Você deve estar ciente dessas coisas e estar preparado para lidar com isso.
parseInt
com um argumento numérico. parseInt
deve analisar seqüências parcialmente numéricas, não truncar números.
O JavaScript calcula exatamente o piso dos números negativos e o restante dos números não inteiros, seguindo as definições matemáticas para eles.
FLOOR é definido como "o maior número inteiro menor que o parâmetro", portanto:
REMAINDER é definido como o "restante" de uma divisão (aritmética euclidiana). Quando o dividendo não é um número inteiro, o quociente geralmente também não é um número inteiro, ou seja, não há resto, mas se o quociente for forçado a ser um número inteiro (e é isso que acontece quando alguém tenta obter o restante ou módulo de um número de ponto flutuante), haverá um não inteiro "sobra", obviamente.
O JavaScript calcula tudo conforme o esperado, portanto, o programador deve ter o cuidado de fazer as perguntas apropriadas (e as pessoas devem ter o cuidado de responder ao que é solicitado!). A primeira pergunta de Yarin NÃO foi "qual é a divisão inteira de X por Y", mas, em vez disso, "o número inteiro de vezes que um determinado número inteiro entra em outro". Para números positivos, a resposta é a mesma para ambos, mas não para números negativos, porque a divisão inteira (dividendo por divisor) será -1 menor que as vezes que um número (divisor) "entra" em outro (dividendo). Em outras palavras, FLOOR retornará a resposta correta para uma divisão inteira de um número negativo, mas Yarin não perguntou isso!
gammax respondeu corretamente, esse código funciona conforme solicitado por Yarin. Por outro lado, Samuel está errado, ele não fez as contas, eu acho, ou ele teria visto que funciona (também, ele não disse qual era o divisor de seu exemplo, mas espero que tenha sido 3):
Restante = X% Y = -100% 3 = -1
GoesInto = (X - Restante) / Y = (-100 - -1) / 3 = -99 / 3 = -33
A propósito, testei o código no Firefox 27.0.1, ele funcionou conforme o esperado, com números positivos e negativos e também com valores não inteiros, tanto para dividendos quanto para divisores. Exemplo:
-100.34 / 3.57: GoesInto = -28, Restante = -0.3800000000000079
Sim, notei que existe um problema de precisão, mas não tive tempo de verificá-lo (não sei se é um problema com o Firefox, Windows 7 ou com a FPU da minha CPU). Para a pergunta de Yarin, porém, que envolve apenas números inteiros, o código da gammax funciona perfeitamente.
O cálculo do número de páginas pode ser feito em uma etapa: Math.ceil (x / y)
O comentário de Alex Moore-Niemi como resposta:
Para Rubyists aqui do Google em busca de divmod
, você pode implementá-lo da seguinte forma:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Resultado:
// [2, 33]
divmod
usa divisão com piso ( Math.floor
), que difere da divisão truncada ( Math.trunc
) quando números negativos estão envolvidos. Este é o caso do pacote NPMdivmod
, Rubydivmod
, SWI-Prologdivmod
e provavelmente muitas outras implementações também.
divmod
existe porque é executado duas vezes mais rápido que o cálculo das duas operações separadamente. Fornecer essa função sem esse benefício de desempenho pode ser confuso.
Se você está apenas dividindo com potências de dois, pode usar operadores bit a bit:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(O primeiro é o quociente, o segundo o restante)
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
.
Você pode usar o ternário para decidir como lidar com valores inteiros positivos e negativos.
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
Se o número for positivo, está tudo bem. Se o número for negativo, ele adicionará 1 por causa de como o Math.floor lida com negativos.
Isso sempre truncará para zero. Não tenho certeza se é tarde demais, mas aqui vai:
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
Se você precisar calcular o restante para números inteiros muito grandes, os quais o tempo de execução JS não pode representar como tal (qualquer número inteiro maior que 2 ^ 32 é representado como float e, portanto, perde precisão), é necessário fazer algum truque.
Isso é especialmente importante para verificar muitos casos de dígitos de cheque que estão presentes em muitos casos de nossa vida diária (números de contas bancárias, cartões de crédito, ...)
Antes de tudo, você precisa do seu número como uma string (caso contrário, você já perdeu a precisão e o restante não faz sentido).
str = '123456789123456789123456789'
Agora você precisa dividir sua corda em partes menores, pequenas o suficiente para que a concatenação de qualquer restante e um pedaço de corda possa caber em 9 dígitos.
digits = 9 - String(divisor).length
Prepare uma expressão regular para dividir a sequência
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
Por exemplo, se digits
for 7, o regexp é
/.{1,7}(?=(.{7})+$)/g
Corresponde a uma substring não vazia de comprimento máximo 7, que é seguida ((?=...)
por um número de caracteres múltiplo de 7. O 'g' é para fazer a expressão percorrer toda a cadeia, sem parar na primeira correspondência.
Agora converta cada parte em número inteiro e calcule os demais reduce
(adicionando novamente o restante anterior - ou 0 - multiplicado pela potência correta de 10):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
Isso funcionará devido ao algoritmo restante "subtração":
n mod d = (n - kd) mod d
que permite substituir qualquer 'parte inicial' da representação decimal de um número pelo restante, sem afetar o restante final.
O código final seria semelhante a:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
3.5 % 2
avaliado em 1,5. Certifique-se de manipular (análise, piso, etc.) conforme necessário #