Using the bcmath functions correctly - php

I've never used the bcmath figures before and having been doing a bit of reading about comparing and manipulating floating point numbers and this has led me to the bcmath functions.
I understand you definitely should use something like the bccomp function when comparing floating point numbers as even if the numbers look the same, they may not be stored the same internally; but is it really necessary to use the other bc functions?
Like what harm is there in adding two floating point numbers together or doing any other math on them? Aren't the floating point figures correct (apart from possibly the last digit if you have a high precision) and thus can be manipulated as you like?

Related

Laravel issue when printing a double field coming from the database

I have an issue with laravel or php (don´t know yet), the issue is the next:
I have a field on my database called debe which value is 3.97 as you can see below. This field is a double(11,2).
When I access to that field on my framework, for example using a dd() it returns the value correctly as you can see below.
The main problem occurs when i'm trying to print into the view, I receive the next:
I dont know why this is happening but right now the only solution that I've found is to round the value using PHP round() function.
Regards
Check this article in the official documentation:
Floating point numbers have limited precision. Although it depends on
the system, PHP typically uses the IEEE 754 double precision format,
which will give a maximum relative error due to rounding in the order
of 1.11e-16. Non elementary arithmetic operations may give larger
errors, and, of course, error propagation must be considered when
several operations are compounded.
Additionally, rational numbers that are exactly representable as
floating point numbers in base 10, like 0.1 or 0.7, do not have an
exact representation as floating point numbers in base 2, which is
used internally, no matter the size of the mantissa. Hence, they
cannot be converted into their internal binary counterparts without a
small loss of precision. This can lead to confusing results: for
example, floor((0.1+0.7)*10) will usually return 7 instead of the
expected 8, since the internal representation will be something like
7.9999999999999991118....
So never trust floating number results to the last digit, and do not
compare floating point numbers directly for equality. If higher
precision is necessary, the arbitrary precision math functions and gmp
functions are available.
You can use the round or number_format functions to get the desired decimals

Fibonacci Series with long numbers php

I am making Fibonacci series for long numbers in PHP. For example my n = 100 and post 92 sequence it starts getting values like 1.2200160415122E+19.
Please help me to understand how to handle such big numbers in PHP.
On first sight I'd say this has nothing to do with the php language. It is a general issue with floating point notation that you simply do not have a precision as with fixed point notation. For tasks like Fibonacci I'd say you need a precision of 1, thus a floating point notation is unsuitable for the task. No way around that.
However there are a number of classes and extensions for php that allow arithmetic with large integers. I suggest you take a look into those:
BC Math
GMP

In PHP, can ceil() ever round up an even division?

I have read a bunch of questions and comments but haven't seen this mentioned, and since others may have the same question, I'm posting it here.
Considering floating point errors, is it ever possible to get a result one point higher than it should be from a ceil($a / $b) where the rest of $a / $b is 0?
If so, since I'm working with positive integers higher than 0, perhaps I should write my_ceil() where I check for $a % $b first and if it's not 0, add 0.1 to $a before calling the built-in function…
If what you appear to be asking is how to use floating points including their correct non-absolute errors in deciding a ceil outcome, the following should guide you:
1) http://www.php.net/manual/en/language.types.float.php
Rational numbers that are exactly representable as floating point
numbers in base 10, like 0.1 or 0.7, do not have an exact
representation as floating point numbers in base 2, which is used
internally, no matter the size of the mantissa. Hence, they cannot be
converted into their internal binary counterparts without a small loss
of precision. This can lead to confusing results: for example,
floor((0.1+0.7)*10) will usually return 7 instead of the expected 8,
since the internal representation will be something like
7.9999999999999991118....
So never trust floating number results to the last digit, and do not
compare floating point numbers directly for equality [my emphasis]. If higher
precision is necessary, the arbitrary precision math functions and gmp functions are available.
Read up
Arbitrary precision math functions : http://uk1.php.net/manual/en/ref.bc.php
And gmp : http://uk1.php.net/manual/en/ref.gmp.php
2) You are caring about floats (as the single input value) when using ceil($float) when ceil will only ever round up to the nearest integer so whatever the floating value is, is irrelevant. You may be considering using the round() function instead. which has it's own ways of dealing with the above floating point inaccuracy issue.
http://php.net/manual/en/function.round.php
To answer the original question of Considering floating point errors, is it ever possible to get a result one point higher than it should be from a ceil($a / $b) where the rest of $a / $b is 0? the answer is YES because of two points:
Float is potentially significantly inaccurate in base10 numbers, and,
You are using the wrong function to get the output you want to the precision you need. In this situation using multiple float numbers you want a function that have built in precision required, such as gmp or maths functions .
Looking at the ceil source code on github, it seems that it is dependent on your C library's ceil function.
Edit: To answer the question – YES, it (probably) can.
I guess this doesn't really have anything to do with ceil() but rather with if the division in question returns a float or integer type value.
According to http://php.net/manual/en/language.operators.arithmetic.php …
The division operator ("/") returns a float value unless the two operands are integers (or strings that get converted to integers) and the numbers are evenly divisible, in which case an integer value will be returned.
So using at least one float value could produce a ceil() "error", but I should be fine with two integers.

Math operations precision in PHP 5, PHP 7

When developing calculator in PHP 5+, can programmer get results without thinking on errors of rounding and imprecise representation of decimal numbers?
I mean built-in perfect ways to get, for example, results with given accuracy.
Or each operation like $x = $y * $z + 0.77 must require to develop additional checks in algorithm like rounding (for avoiding errors)?
So errors or imprecision - is up to PHP built-in core or up to developer?
PHP 7 has 64-bit support, what is the improvement on this direction (accuracy of calculations)?
When developing calculator in PHP 5+, can programmer get results without thinking on errors of rounding and imprecise representation of decimal numbers?
Simple answer is No.
Doing arithmetics on decimal basis by using a binary machine like a computer can and will always produce some kind of error.
Many details are explained in this article, it's quite a complex subject.
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Simple example from the decimal world:
The fraction 1/3 can not be expressed as a finite floating point number in decimal notation. Often we try it by writing 0.333333333... but that's not 100% accurate.
Same applies to binary number arithmetics.
[Edit]
If you need a very high degree of precision than you should have a look at phps BC math functions http://php.net/manual/en/ref.bc.php
I don't think there's anything in PHP 7 that will change this. AS #maxhb points out, doing floating point arithmetic is inherently imprecise so you must mind rounding errors.
The 64-bit capability does not fundamentally change this.

why 0.1+0.2-0.3= 5.5511151231258E-17 in php [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
The accuracy of PHP float calculate
when i executed the code below in eclipse , the result was not 0 but 5.5511151231258E-17
$a = 0.1+0.2-0.3;
echo $a;
could someone tell me why?
This is because floating point numbers have limited precision.
You can find more information about this trait on this page in the PHP manual.
Floating point numbers have limited precision. Although it depends on
the system, PHP typically uses the IEEE 754 double precision format,
which will give a maximum relative error due to rounding in the order
of 1.11e-16. Non elementary arithmetic operations may give larger
errors, and, of course, error progragation must be considered when
several operations are compounded.
Additionally, rational numbers that are exactly representable as
floating point numbers in base 10, like 0.1 or 0.7, do not have an
exact representation as floating point numbers in base 2, which is
used internally, no matter the size of the mantissa. Hence, they
cannot be converted into their internal binary counterparts without a
small loss of precision. This can lead to confusing results: for
example, floor((0.1+0.7)*10) will usually return 7 instead of the
expected 8, since the internal representation will be something like
7.9999999999999991118....
So never trust floating number results to the last digit, and never
compare floating point numbers for equality. If higher precision is
necessary, the arbitrary precision math functions and gmp functions
are available.
Please note that this is not a trait specific to PHP; it is just the way floating point numbers work.
You're running into PHP's floating point precision issues. All languages have them, you've just found PHP's.
This is not PHP specific, as others have mentioned. However, you can avoid limited floating point precision by using round():
<?php
$a = 0.1+0.3-0.2;
echo round($a, 2);
?>
Of course you will need to know the number of digits beforehand.
It's because computers can't accurately represent floating point numbers. This isn't specific to PHP.
See here for details.

Categories