Handling decimals with high precision in PHP

Tram Ho

Question

Most current web applications handle decimals in several forms: Currency, coordinates, measurements, mathematical constants. However, you may not know, PHP does not provide a clear standard for dealing with cases of decimal numbers that require high accuracy. Of course there will be cases where accuracy is not as important, or at least not as important as application performance.

The PHP float type is actually an IEEE 754–1985 double , that is, it is a floating-point binary, and therefore it is not capable of representing certain decimal numbers, for example. example 0.2. This is because that value is stored as an integer a (integer) multiplied by 2 powers of an integer b (integer).

c = a × 2 b

Where a and b are 2 integers, but when there are no integer solutions for a and b, the result number will be an approximation. This leads to what we don’t want:

The arithmetic system we are taught in school and used in our daily lives is of course the decimal number . When we use float , we use the binary number type to represent a decimal number, because we can perform binary calculations very quickly on a computer, because computers use binary stool. To calculate exponent 2, all we need to do is left shift a bit.

In order to represent decimal numbers correctly, we need to use powers of 10 instead of powers 2. But unfortunately, most computer architectures do not support a factor of 10 (decimal). , which is 2 (binary), so we need to calculate that power of 10.

The trade-off here is exchanging performance for accuracy .

When you need accuracy, this tradeoff is easy to do because you only need to provide more CPU to compensate for the performance, but you can’t change the fundamental limits of the architecture itself. For example, most PHP applications will have a “bottleneck” in the filesystem system or in the network layer, or somewhere …

How to represent decimal correctly in PHP?

There are several existing solutions that PHP has provided for a long time are bcmath and gmp . These extensions provide an interface for creating and manipulating extremely large numbers and precise numbers.

The common intermediary type is string ( bcmath accepts inputs and outputs are strings) and there are some abstract classes that will take care of that for you. Searching for “decimal” on Packagist will give you lots of results, but obviously none of them is the best of them all. This indicates that most applications require the correct number to use these extensions directly, or use their own abstract classes.

I will introduce to you a standard for dealing with decimal numbers in PHP, this is not the only way, but at least a recommendation for you to choose.

Decimal extension

This extension supports floating-point decimals with precision rounding functions or arbitrary precision. Applications based on exact numbers can use the Decimal class of extension instead of using float or string .

  • Decimal is an object, so you can type-hint Decimal.
  • Support arithmetic and arithmetic comparison, which abstract classes (not extensions) cannot do (or at least cannot yet).
  • Accuracy is defined as the number of significant digits and the ratio is the number of digits after the comma. For example, the number 1.23E-1000 will have the ratio of 1002 but the accuracy is 3. Decimal uses precision, while bcmath uses the ratio. Here I do not comment on how one is better than the other, but it makes an important difference between the two.
  • Supporting mathematical notation, you can use strings of the form 1.23E-1000 to represent a number, at the time of this writing, you can’t do this with bcmath .
  • Calculations are significantly faster than bcmath , though performance is probably not the deciding factor here.
  • It uses the same internal C library as that of Python’s decimal module 3.
  • You can try it first with online sanbox .

Decimal with SQL

If you are building an application with PHP, chances are you are using MySQL or PostgreSQL. Decimal provides a function for you to easily get / save values ​​between database and program.

For example, if you want to save a number with 20 digits to the left of the comma and 4 digits to the right (i.e. has an accuracy of 24). PDO will receive and store values ​​as a string , avoiding the use of floats , for example:

Conclusion

It is rare to have to calculate decimals with high precision, but if you are working with a money-related application, this is extremely important, and I hope the article This can help you figure out how to fix the problem. To learn more about the Decimal extension, you can find specific documents at http://php-decimal.io/ .

Share the news now

Source : Viblo