Enquanto programava em C ++ há alguns dias, cometi esse erro (que tenho histórico de cometê-lo!). Em uma parte do meu código, eu tinha 1/6 e esperava que fosse 0,16666666666, o que não é o caso. Como todos sabem, o resultado é 0 - C, C ++, Java, Python, todos se comportam da mesma maneira.
Eu publico na minha página do Facebook e agora há um debate sobre se existe uma linguagem de programação onde 1/6
o mesmo se comporta 1.0/6.0
.
programming-languages
Pouya
fonte
fonte
>> 1 / 6
->== 0.166666666666667
1/6
é realmente 1/6 (tipo fracionário) que, coagido aDouble
, é 1,66666 ...Respostas:
Todo mundo esqueceu Pascal?
1/6
rendimentos0.1666666...
(com qualquer precisão suportada).1 div 6
rendimentos0
É discutível se a regra C é um erro. Quase todos os operadores aritméticos de C, onde os operandos são do mesmo tipo, produzem um resultado do mesmo tipo. Há algo a ser dito para consistência.
Além disso, como C é direcionado principalmente ao código no nível do sistema, a maioria dos programas em C não usa ponto flutuante. Ao mesmo tempo, adicionar acidentalmente código de ponto flutuante a um programa que não precisava dele poderia ser um problema sério. Provavelmente ainda é esse o caso de pequenos sistemas embarcados - que, novamente, são um grande alvo para C.
Na maioria dos programas C, truncar a divisão inteira provavelmente é exatamente o que você deseja.
Se
1 / 6
produziu um resultado de ponto flutuante em C, então:double
pode parecer a escolha natural, mas você pode preferir a precisão extra delong double
)C poderia ter fornecido operadores separados para os dois tipos de divisão, mas o segundo ponto acima ainda se aplicaria: qual dos três tipos de ponto flutuante seria usado para o resultado? E como é fácil obter a divisão de ponto flutuante, se você precisar (use uma constante de ponto flutuante para um ou ambos os operandos ou converta um ou ambos os operandos para um tipo de ponto flutuante), aparentemente não era ' Não considerou isso importante.
Na versão de 1974 do manual C (quatro anos antes da publicação da primeira edição da K&R), Ritchie nem menciona a possível confusão:
que diz que, se ambos os operandos são do tipo
int
ouchar
, o resultado é do tipoint
.Sim, é uma fonte de confusão para alguns programadores de C, especialmente iniciantes - mas C não é conhecido por ser muito amigável para iniciantes.
fonte
1.666666...
, o que está claramente errado. Meu coxo desculpa é que o programa de teste Pascal eu escrevi impresso1.6666666666666667E-0001
Na verdade, esse comportamento foi alterado no Python 3 e agora se comporta como o esperado (
//
agora é usado para divisão inteira).fonte
/
sempre produz um valor de ponto flutuante e um operador separado (div
) é usado para divisão inteira.Fora de idiomas importantes, JavaScript. 1,0 / 6,0 = 1/6 = 0,1666666666666666666.
Eu não vejo isso como surpreendente. Como regra geral, se um idioma distingue entre tipos numéricos de número inteiro e de ponto flutuante, a divisão de dois números inteiros produzirá um número inteiro truncado em vez de flutuante. Caso contrário, provavelmente será o padrão para operações de ponto flutuante. Esse deve ser o comportamento esperado da parte do programador.
Lembre-se de que há outras coisas que também podem estar em jogo aqui, como o operador de divisão inteira separado já mencionado ou a conversão implícita de tipos.
fonte
Existem muitos idiomas em que
((1/6)*6)
resulta em 1, e não em 0. Por exemplo, PL / SQL, muitos dialetos BASIC, Lua.Acidentalmente, em todos esses idiomas 1/6 resulta em 0,1666666667 ou 0,16666666666667 ou algo semelhante. Eu escolhi a ((1/6) * 6) == 1 variante para se livrar dessas pequenas diferenças.
fonte
((1/6)*6)==1
variante para se livrar dessas pequenas diferenças, mas parece que superestimei as habilidades matemáticas de algumas pessoas.Haskell trata 1/6 e 1.0 / 6.0 como sendo idênticos 0.16666666666666666. Também processa 1 / 6.0 e 1.0 / 6 como sendo o mesmo valor também.
Isso ocorre porque os tipos numéricos básicos em Haskell não são exatamente os mesmos de outros idiomas. A verdadeira divisão inteira é um pouco ... complicada.
fonte
Sim, Perl faz. O one-liner
resulta na saída de:
Eu acredito que o PHP funciona da mesma maneira.
Editado para adicionar: Eu também acredito que uma condição necessária (mas não suficiente)
1/6 == 1.0/6.0
para o idioma em questão seja fracamente digitada.fonte
/
está sobrecarregado automaticamente dependendo dos tipos dos argumentos, mas que parece ser uma violação do princípio do menor Astonishment para me ...No Squeak Smalltalk, os
/
números inteiros criam objetos Fraction. Portanto, embora isso não seja o mesmo que divisão de flutuação, ainda(1/6)*6
retorna 1.fonte
Sim, acabei de verificar minha TI-99 / 4A incorporada no TI BASIC . Como trata todas as expressões numéricas como ponto flutuante, a operação de divisão também é ponto flutuante.
fonte
VB ( VB.Net , VB6 , VBA ...)
O operador de divisão inteira é \
fonte
MATLAB. Literais numéricos são duplos por padrão.
fonte
Clojure usa frações por padrão. Não é o mesmo que 1.0 / 6.0, mas você pode convertê-lo com
float
oudouble
quando precisar.fonte
Surpreendentemente, parece funcionar corretamente no Windows PowerShell (versão 3) .
Também parece funcionar no Python 3, como mencionado no sepp2k. Os outros dois idiomas que eu tenho prontamente disponíveis no REPL, Scala e Ruby, ambos fazem divisão inteira e produzem 0.
fonte
A linguagem Rexx sempre produz uma resposta aritmeticamente correta. Por exemplo: 5/2 = 2,5. Rexx é uma ótima linguagem que não foi utilizada o suficiente. Em teoria, quando um compilador não pode determinar o que você deseja, é melhor fazer a matemática correta; no entanto, isso pode não ser eficiente. Rexx também fornece o operador //.
fonte