Home  >  Article  >  Backend Development  >  What should I do if php cannot calculate floating point numbers?

What should I do if php cannot calculate floating point numbers?

藏色散人
藏色散人Original
2021-11-19 09:50:161648browse

php cannot calculate floating point numbers because the underlying binary of the computer cannot accurately represent floating point numbers. The solution is to use a class library or function library for accurate calculations, such as the BC high-precision function library in php.

What should I do if php cannot calculate floating point numbers?

The operating environment of this article: windows7 system, PHP version 7.1, DELL G3 computer

What should I do if php cannot calculate floating point numbers?

Floating point number calculation problems in php

If you use php's -*/ to calculate floating point numbers, you may encounter some problems with incorrect calculation results. , for example, echo intval(0.58*100); will print 57 instead of 58. This is actually a bug in the computer's underlying binary that cannot accurately represent floating point numbers. It is cross-language. I also encountered this problem using python. So basically most languages ​​provide class libraries or function libraries for precise calculations. For example, PHP has a BC high-precision function library. Here are some commonly used BC high-precision functions.

Example

<?php    
$f = 0.58;    
var_dump(intval($f * 100)); 
//为啥输出57
?>

Why is the output 57? Is it a bug in PHP?

I believe that many students have had such questions, because just asking me similar questions There are many people, not to mention people often ask on bugs.php.net...

To understand this reason, we first need to know the representation of floating point numbers (IEEE 754):

Floating Points, taking a 64-bit length (double precision) as an example, will be represented by 1 sign bit (E), 11 exponent bits (Q), and 52 mantissa bits (M) (a total of 64 bits).

Sign bit: The highest bit represents the sign of the data, 0 represents a positive number, and 1 represents a negative number.

Exponent bit: represents the power of the data with base 2, and the exponent is represented by an offset code

Mantissa: represents the valid digits after the decimal point of the data.

The key points here It lies in the representation of decimals in binary. Regarding how to represent decimals in binary, you can search on Baidu. I will not go into details here. The key thing we need to understand is that for binary representation, 0.58 is an infinitely long value (the numbers below Omitting the implicit 1)..

The binary representation of 0.58 is basically (52 bits): 00101000111101011100001010001111010111000010100011110.57 is basically (52 bits): 001000111101011100 001010001111010111000010100011110 and binary of both, if just pass If these 52 bits are calculated, they are: www.111cn.net

0.58 -> 0.579999999999999960.57 -> 0.5699999999999999 As for the specific floating point multiplication of 0.58 * 100, we do not consider that details, if you are interested You can see (Floating point), let's look at it vaguely with mental arithmetic... 0.58 * 100 = 57.999999999

Then if you intval it, it will naturally be 57...

It can be seen that the key to this problem The point is: "Your seemingly finite decimal is actually infinite in the binary representation of the computer"

So, don't think this is a bug in PHP, this is what it is...

There is an inaccuracy in PHP floating point processing -*%/

For example:

  $a = 0.1;
  $b = 0.7;
  var_dump(($a + $b) == 0.8);

The printed value is boolean false

This is for What? The PHP manual has the following warning message for floating point numbers:

Warning

Floating point precision

Obviously simple decimal fractions like 0.1 or 0.7 cannot be made without losing a little bit of precision In case of conversion to internal binary format. This can lead to confusing results: for example, floor((0.1 0.7)*10) will usually return 7 instead of the expected 8, because the internal representation of the result is something like 7.9999999999….

This is related to the fact that it is impossible to express certain decimal fractions accurately with a finite number of digits. For example, 1/3 in decimal becomes 0.3333333. . .

So never believe that the floating point number result is accurate to the last digit, and never compare whether two floating point numbers are equal. If you really need higher precision, you should use arbitrary precision mathematical functions or gmp functions

The code is as follows:

<?php
$a = 0.1;
$b = 0.7;
var_dump(bcadd($a,$b,2) == 0.8);
  bcadd — 将两个高精度数字相加
  bccomp — 比较两个高精度数字,返回-1, 0, 1
  bcp — 将两个高精度数字相除
  bcmod — 求高精度数字余数
  bcmul — 将两个高精度数字相乘
  bcpow — 求高精度数字乘方
  bcpowmod — 求高精度数字乘方求模,数论里非常常用
  bcscale — 配置默认小数点位数,相当于就是Linux bc中的”scale=”
  bcsqrt — 求高精度数字平方根
  bcsub — 将两个高精度数字相减

 Completed some examples

 php BC high-precision function library Contains: addition, comparison, division, subtraction, remainder, multiplication, nth power, configure the default number of decimal points, and square. These functions are more useful when it comes to monetary calculations, such as e-commerce price calculations.

Note: Regarding the number of digits set, the excess is discarded instead of rounded.

Recommended learning: "PHP Video Tutorial"

The above is the detailed content of What should I do if php cannot calculate floating point numbers?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn