I have some prices and discount amounts that will be stored in config variables in PHP code. I’m wondering if I need to store them as strings.
For example, is it safe to do the following?
$price = 14.95;
$volume_discount = 0.3;
or should I store them as strings?
$price = '14.95';
$volume_discount = '0.3';
I know that comparing floating point numbers and doing calculations with floating point numbers can yield unexpected results, unless you use BC Math. But I’m wondering about just printing out the stored values as is. I tried echoing the float versions and they displayed as expected, but I’m wondering if that is reliable.
Note: I’ve used the term expected to explain what a layman would expect. As Eric points out, precise decimal floating point numbers is actually not the expected result.
EDIT: The code I am concerned with at the moment, checks the quantity and determines if the discount should be applied. Then does the following calculation:
$price -= round($price * $volume_discount, 2);
I normally use number_format to format the price for display, but I commented out the formatting for my testing. So far, regardless of price or discount values, PHP has been giving me the desired result. JavaScript, however, does not always give me the desired result. That is what led me to look at my PHP code again.
Obviously, I will adjust the JavaScript because that is where the error shows up, but I was trying to decide if I need to refactor my PHP code.
The numbers that illustrated the problem to me were 149.95 * 0.3. PHP displays 44.985 and JavaScript displays 44.98499999999999. So, even after rounding to two decimal places, I get different numbers.
Interpreting the decimal numeral “14.95” and storing it in a binary floating-point object requires a floating-point operation: Conversion from decimal to binary floating-point. Therefore, this is a floating-point operation and is subject to rounding error.
That conversion might happen when the source text is interpreted by a compiler or interpreter or at run-time, but it does happen and is subject to rounding error.
(Your question asserts that comparing and calculating with floating-point numbers yields unexpected results. This is true only if you do not expect the operations to obey the specification for those operations. You can avoid unexpected results by learning the specifications and therefore learning what to expect.)