16. 02. 2020

As in other languages, numbers in PHP are represented in the binary system (the system of ones and zeros), so some mathematical operations may produce slightly different results than we would expect. This page gives an overview of the behaviour of calculations in different contexts. At least a basic knowledge of **numerical techniques** and **number systems** is needed to understand it.

The way numbers are represented is characterized by the data type, for example integer is converted directly from source code from decimal to binary. We don't have to worry about converting numbers at all, everything is done automatically.

The consequence of this conversion is that the maximum value of an integer is determined by the number of bits available in memory. On 32-bit PHP the range is from `-2,147,483,648`

to `-2,147,483,647`

(~ ± 2 billion), 64-bit PHP has a range from `-9,223,372,036,854,775,808`

to `-9,223,372,036,854,775,807`

(~ ± 9 quintillion). The maximum value can always be obtained by calling the constant `PHP_INT_MAX`

.

Decimal numbers are stored in the **float** data type, which has limited precision, so it is stored internally as a pair of numbers that are subject to the mathematical operation `mantissa * (2^exponent)`

. The practical consequence is that we are able to store a relatively large number (on the order of billions) in a small number of bits, just not very precisely.

The consequence of using the **float** data type is that the result of calculating `1 - 0.9`

is not exactly `0.1`

.

Example from web forums:

$x = 0.3;$y = 0.4;echo 0.7 - $x - $y; // prints -5.5511151231258E-17

However, if we adjust the numbers slightly:

$x = 6.5;$y = 7.5;echo 14.0 - $x - $y; // prints 0

This issue is discussed in general in a separate article on VTM.e15.cz: Why computers have problems with decimal numbers, or in general about floating point on Wikipedia.

Generally, it is a good idea to round the result after the calculation, or avoid decimals altogether. For example, store the price not in crowns (like 14.90) but in pennies (like 1490) and then work with it exactly. Rounding is discussed in the next section of this article.

$a = 5;$b = 3;echo $a + $b;

Common mathematical conventions can be used for operations, which respect the precedence of operators according to the rules of mathematics (multiplication takes precedence over addition, etc.). Values can be written directly or read in via variables.

It may not be obvious at first glance, but in the math example, the equals sign (

`=`

) is not written. Hence, it follows that only simple`binary operations`

can be solved, which always work with only`two elements`

(don't count equations, you have to use a specialized library for that).

In the

`result`

column, I list what is printed assuming:

$a = 5;$b = 3;$c = 10;

Operation | Mark | Mark in word | Example of notation | Result |
---|---|---|---|---|

Addition | `+` |
Plus | `echo $a + $b;` |
8 |

Subtraction | `-` |
Minus | `echo $a - $b;` |
2 |

Multiplication | `*` |
Asterisk | `echo $a * $b;` |
15 |

division | `/` |
slash | `echo $a / $b;` |
1.6666666666667 |

brackets | `( )` |
brackets | `echo $a + ($b * $c);` |
35 |

String concatenation | `.` |
Period | `echo $a . $b . $c;` |
5310 |

Remainder after division | `%` |
Percent | `echo $a % $b;` |
2 |

Adding one | `++` |
two pluses | `echo $a++;` |
6 |

Subtract one | `--` |
two minus | `echo $a--;` |
4 |

Power | `**` |
two asterisks | `echo $a ** $b;` |
125 |

The power operator (double asterisk) is only available from PHP 7.1 onwards. In other versions of PHP you must use the universal function

`pow($a, $b)`

.

If you are solving some common computational task, most likely there is already a function directly in PHP, here is an annotated overview of them.

Normal rounding is done with the round() function, it has 3 parameters:

- Rounded number
- Optional: Precision (to how many decimal places)
- Optional: Halving value (from what value to round up)

round(5); // 5round(5.1); // 5round(5.4); // 5round(5.5); // 6round(5.8); // 6round(5483.47621, 2); // 5483.47round(5483.47621, -2); // 5500

There is also a floor() function for rounding down and a ceil() function for rounding up.

Watch out for data types!All rounding functions return the result as

`float`

, even if the result is an integer.If you want to treat the result as an integer, it is important to overtype the result. For example:

`echo (int) round(3.14);`

PHP works with different data types, for example with **float** it can easily happen that the result of `round()`

is not a number with finite decimal expansion. For output, I recommend using the `number_format()`

function, which I discuss below.

These are used for a lot of different calculations and are based on the unit circle. They are used, for example, in plotting circles, ellipses, displacements and so on.

Calculate the angle from `x`

and `y`

. Conversion of Cartesian and polar coordinates.

Based on the unit hyperbola. Their definitions can be easily described by using similes:

- Ellipse, Circle, Circle with radius 1
- Hyperbola, Equiaxial hyperbola, Unit hyperbola

They are used, for example, in terrain generation and physical simulation.

Based on the unit hyperbola.

echo sin(30); // -0.98803162409286echo sin(deg2rad(30)); // 0.5echo cos(deg2rad(123)); // -0.54463903501503echo 1/tan(deg2rad(45)); // 1 (onen cotangent)echo sin(deg2rad(500)); // 0.64278760968654echo atan2(deg2rad(50), deg2rad(23)); // 1.1396575860761

Sometimes it may happen that we need to process a mathematical expression as a user string, for example `5+2^(1+3/2)`

.

There is no easy way to process such input in PHP, but I have programmed a series of libraries that address this issue.

For details, see the separate article Calculator in PHP: Processing a mathematical expression as a string.

Large numbers and decimals are stored as floats in PHP, plus they are rounded to about 15 decimal places, which can sometimes be annoying. This is why the **BCMath Arbitrary Precision Mathematics library was created**.

Numbers are represented as **strings** in this library, so they are not limited by the imprecision of **float**, but the operations performed are several orders of magnitude slower (but still faster than if we programmed such a function ourselves).

For example, if we want to get a square root from 2 to 3 decimal places, we just call:

echo bcsqrt('2', 3); // 1.414

**Jan Barášek** Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Články píše Jan Barášek © 2009-2023 | Kontakt | Mapa webu

Status | Aktualizováno: ... | en