PHP浮点计算错误时减去 [英] PHP float calculation error when subtracting

查看:101
本文介绍了PHP浮点计算错误时减去的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很奇怪的问题。如果我减去2个浮动变量,其中一个是数学运算的结果,那么我得到一个错误的值。
$ b 示例:

 的var_dump($剩余); 
var_dump($ this-> hours_sub ['personal']);
echo $ remaining- $ this-> hours_sub ['personal'];

这就是输出:

  float 5.4 
float 1.4
5.3290705182008E-15



5.4-1.4 应该是 4
如果添加两个值,结果是正确的。



我的错误在哪里?
它不能是一个四舍五入的问题。
解决方案

如果仍然有人到达这个页面,类似的问题,其中浮动数字减法导致错误或奇怪的值。
我想用更多的细节来解释这个问题。

它与PHP没有直接关系,它不是一个bug。
但是,每个程序员都应该知道这个问题。


二十年前,这个问题甚至耗费了很多时间。 1991年2月25日,在MIM-104爱国者导弹电池中进行浮点数计算时,这个问题阻止了它在沙特阿拉伯宰赫兰的飞来飞行导弹的拦截,造成了死亡来自美国陆军第14军需官支队的28名士兵。

但为什么会发生?

原因是浮点数值代表有限的精度。所以,在任何处理之后,一个值
可能没有相同的字符串表示。它也
包括写你的脚本中的浮点值,直接
打印它没有任何数学运算。

只是一个简单的例子: p>

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

你可以期望它打印 0.01 ,对?
但它会打印一个非常奇怪的答案像 0.009999999999998



像其他数字一样,浮点数double或者float作为0和1的字符串存储在内存中。浮点数与整数的不同之处在于我们如何解释0和1,当我们想看看它们时。他们存储的标准有很多。

浮点数通常从左到右依次放入计算机数据中作为符号位,指数字段和有效位数或尾数。 / p>

由于缺少足够的空间,十进制数字在二进制文件中不能很好地表示。所以,你不能正确表达 1/3 ,因为它是 0.3333333 ... ,对不对?为什么我们不能将 0.01 表示为二进制浮点数是出于同样的原因。 1/100 0.00000010100011110101110000 ..... 带有重复 10100011110101110000 0.01 以简化和系统截断的形式保存,那么

01000111101011100001010 在二进制中,当它被转换回十进制时,它将被读为像 0.0099999 .... 取决于系统(64位计算机将给你比32位更好的精度)。在这种情况下,操作系统决定是否打印它,或者如何以更易读的方式打印。所以,这是机器相关的,他们想如何表示它。但是可以用不同的方法在语言层面加以保护。如果你使用

  echo number_format(0.009999999999998, 2); 

它会打印 0.01



这是因为在这种情况下,你应该指出它应该如何读取,以及你需要多少精度。

I have a very strange issue. If I subtract 2 float vars where one is the result of a mathematical operation I get a wrong value.

Example:

var_dump($remaining);
var_dump($this->hours_sub['personal']);
echo $remaining-$this->hours_sub['personal'];

This it the output:

float 5.4
float 1.4
5.3290705182008E-15

5.4-1.4 should be 4 If I add the two values the result is correct.

Where is my mistake? It can not be a rounding issue.

解决方案

If still somebody reach this page with similar problems where floating number subtraction causes error or strange values. I want to explain this problem with a bit more details.

It is not directly related to PHP and it is not a bug. However, every programmer should be aware of this issue.

This problem even took many lives two decades ago.

On 25 February 1991 this problem in floating number calculation in a MIM-104 Patriot missile battery prevented it intercepting an incoming Scud missile in Dhahran, Saudi Arabia, contributing to the death of 28 soldiers from the U.S. Army's 14th Quartermaster Detachment.

But why it happens?

The reason is that floating point values represent a limited precision. So, a value might not have the same string representation after any processing. It also includes writing a floating point value in your script and directly printing it without any mathematical operations.

Just a simple example:

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

You would expect it to print 0.01, right? But it will print a very strange answer like 0.009999999999998

Like other numbers, floating point numbers double or float is stored in memory as a string of 0's and 1's. How floating point differs from integer is in how we interpret the 0's and 1's when we want to look at them. There are many standards how they are stored.

Floating-point numbers are typically packed into a computer datum as the sign bit, the exponent field, and the significand or mantissa, from left to right....

Decimal numbers are not well represented in binary due to lack of enough space. So, you can't express 1/3 exactly as it's 0.3333333..., right? Why we can't represent 0.01 as a binary float number is for the same reason. 1/100 is 0.00000010100011110101110000..... with a repeating 10100011110101110000.

If 0.01 is kept in simplified and system-truncated form of 01000111101011100001010 in binary, when it is translated back to decimal, it would be read like 0.0099999.... depending on system (64bit computers will give you much better precision than 32-bits). Operating system decides in this case whether to print it as it sees or how to make it in more human-readable way. So, it is machine-dependent how they want to represent it. But it can be protected in language level with different methods.

If you format the result using

echo number_format(0.009999999999998, 2);

it will print 0.01.

It is because in this case you instruct how it should be read and how precision you require.

这篇关于PHP浮点计算错误时减去的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆