Pergunta

Got outro problema cálculo matemático novamente.

$a = 34.56

$b = 34.55

$a fazer alguns cálculos para obter este número

$b está fazendo o arredondamento mais próximo de 0,05 para obter este número

O que acontece é

$c = $b - $a

supostamente eu deveria ser -0.01, mas eu echo o $c é mostrar -,00988888888888

Eu tento usar number_format($c, 2), mas a saída é de 0,00,

Como posso ter certeza de $a e $b é exatamente 2 casas decimais, nenhum número escondido na parte de trás.

no meu php number_format conhecimento só é capaz de formatar a exibição, mas o valor não é realmente 2 decimal,

Espero que eu possa obter ajuda de aqui. Isso realmente me frustrado.

Foi útil?

Solução

Tente sprintf ("%.2f", $c);

números de ponto flutuante são representados em notação IEEE com base nas potências de 2, então terminar números decimais não pode ser um número binário de terminação, é por isso que você obtém os dígitos à direita.

Como sugerido por Variable Length Coder, se você sabe a precisão que você quer e isso não muda (por exemplo, quando você está lidando com dinheiro) pode ser melhor usar apenas números de ponto fixo ou seja, expressar os números como centavos, em vez de dólares

$a = 3456;

$b = 3455;

$c = $b - $a;

sprintf ("%.2f", $c/100.0);

Desta forma, você não terá quaisquer erros de arredondamento se você fizer um monte de cálculos antes de imprimir.

Outras dicas

Use round() :

$c = round($b - $a, 2);

Nota:. você também pode escolher o modo de arredondamento conforme apropriado

Editar: Ok eu não conseguir o que sprintf() está fazendo isso number_format() não é:

$c = number_format($b - $a, 2);

vs

$c = sprintf("%.2f", $b - $a);

?

Cálculo Nativo:

$a = 34.56;
$b = 34.55;
$c = $b - $a; // -0.010000000000005    

funciona como esperado (Utilize sempre funções BC para cálculos com números reais, a questão é para todas as plataformas baseadas C!):

$a = '34.56';
$b = '34.55';
$c = bcsub($b, $a, 4); // -0.0100    

Eu também corri para este problema recentemente ao fazer cálculos com flutuadores. Por exemplo, I tinha 2 flutuadores que, quando subtraída e formatado, o valor foi de -0,00.

$floatOne = 267.58;
$floatTwo = 267.58;
$result = number_format($floatOne - floatTwo, 2);
print $result; //printed a string -0.00

O que fiz foi:

$result = abs($floatOne - $floatTwo);// Made the number positive
print money_format('%i', $result); // printed the desired precision 0.00

Na minha solução Eu sei que floatOne nunca será inferior a floatTwo. A money_format função é apenas definida se o sistema tem capacidades strfmon, Windows não.

Você correr em uma das armadilhas de números de ponto flutuante; que eles não podem sempre representar frações decimais exatas. Se você quiser valores decimais exatos, você é melhor fora de usar números inteiros e dividindo pela precisão que você quer no final.

Por exemplo, se você estiver fazendo cálculos em jangadas represeting dólares (ou sua moeda favorito), você pode querer realmente fazer seus cálculos em centavos inteiros.

Você pode muito ordenadamente contornar todos esses problemas simplesmente usando a biblioteca bcmath.

Apenas lembre-se de ler a documentação e ter cuidado se você está passando argumentos como cordas ou como tipos de dados numéricos.

Se alguém ainda chegar a essa página com problemas semelhantes, onde o número de subtração flutuante provoca valores de erro ou estranhos. Quero explicar esse problema com um pouco mais de detalhes. O culpado é os números de ponto flutuantes. E sistemas operacionais diferentes e diferentes versões de linguagens de programação pode se comportar de forma diferente.

Para ilustrar o problema, vou explicar por que com um exemplo simples abaixo.

Ele não está directamente relacionado com PHP e não é um bug. No entanto, cada programador deve estar ciente desta questão.

Este problema ainda teve muitas vidas, há duas décadas.

Em 25 de fevereiro de 1991 este problema em flutuante cálculo número em um Patriot bateria de mísseis MIM-104 impediu interceptar um míssil Scud de entrada em Dhahran, na Arábia Saudita, contribuindo para a morte de 28 soldados do 14º Exército do EUA Quartermaster Destacamento.

Mas por que isso acontece?

A razão é que valores de ponto flutuante representam uma precisão limitada. Assim, um valor pode não têm a mesma representação de cadeia após qualquer processamento. Isso também inclui a escrita de um valor de ponto flutuante em seu script e directamente imprimi-lo sem quaisquer operações matemáticas.

Apenas um exemplo simples:

$a = '36';
$b = '-35.99';
echo ($a + $b);

Você esperaria que imprimir 0,01, certo? Mas ele irá imprimir uma resposta muito estranho como ,009999999999998

Como outros números, números de ponto flutuante dobrar ou flutuante é armazenado na memória como uma seqüência de 0 e 1 do. Como flutuante difere ponto de inteiro está em como nós interpretamos os 0 e 1, quando queremos olhar para eles. Há muitos padrões como eles são armazenados.

números de ponto flutuante são tipicamente embalados em um dado computador como o bit de sinal, o campo de expoente, e do significando ou mantissa, da esquerda para a direita ....

Os números decimais não são bem representados em binário devido à falta de espaço suficiente. Então, uou não podem expressar 1/3 exatamente como é 0,3333333 ..., certo? Por que não podemos representar 0,01 como um número flutuante binário é pela mesma razão. 1/100 é ,00000010100011110101110000 ..... com um repetindo 10100011110101110000.

Se a 0,01 é mantida de forma simplificada e truncada do sistema de 01000111101011100001010 em binário, quando é traduzido de volta para decimal, seria lido como 0,0099999 .... dependendo do sistema (computadores de 64 bits lhe dará muito melhor precisão do que 32-bits). sistema operacional decide, neste caso, se é necessário imprimir-lo como ele vê ou como fazê-lo em mais maneira legível. Então, é como eles querem representá-lo dependente da máquina. Mas ele pode ser protegido no nível de linguagem com diferentes métodos.

Se você formatar o resultado, eco number_format (,009999999999998, 2); ele irá imprimir 0,01.

É porque neste caso você instrui como deve ser lido e como precisão que necessita.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top