1

I'm having an issue when trying to do some calculations within Woocommerce, and it looks like I'm getting a floating-point precision error. I.e: my end sum is 448.99, but actually I need my sum to be 449.00.

Let's take a look at how I arrive to this calculation:

First I save prices of my currently selected variations in an array

$regular_price_array[$variation_key] = (float)get_post_meta($selected_variation_ids[$variation_key]['variation_id'], '_regular_price', true);

Result:

array(6) { [64]=> float(74) [65]=> float(99) [66]=> float(89) [67]=> float(89) [68]=> float(59) [69]=> float(149) }

Then I save my discounts in an array:

$variation_discount_array[$discount_key] = (float)$selected_variation_ids[$discount_key]['discount'];

Result:

array(6) { [0]=> float(19.66) [1]=> float(19.68) [2]=> float(19.68) [3]=> float(19.68) [4]=> float(19.68) [5]=> float(19.68) }

Then I try to do a basic calculation of PRICE * (1 - DISCOUNT/100), then add up each of these prices. This is where the problem happens, due to PHP's floating point precision I think.

$discount_variation_price[$innerKey] = $reg_prices * number_format((1 - $discount/100),4);

Result:

array(6) { [64]=> float(59.4368) [65]=> float(79.5168) [66]=> float(71.4848) [67]=> float(71.4848) [68]=> float(47.3888) [69]=> float(119.6768) } 

If you were to do the math yourself just on the first one you would see the issue. You end up getting ~59.45(which makes up for that last cent), but of course it wouldn't just work like that.

I've tried using bcmath() but on my installation I'm getting an error that this function is undefined and can't find much about it so I'm assuming it's uncommon to use this function in a WordPress website.

All that being said, I'm not exactly well-versed on this particular subject, so I'm wondering what's my best course of action to actually get the sum I need? I'm utterly stumped! Thanks!

Note: the (float) is type-cast here, but before if I didn't type cast it only the discount would be a float and the price would be string. The error still remained though, and I thought maybe changing both to a float would help. This had no impact.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Darthmaul
  • 151
  • 1
  • 10
  • Work in cents, not float. Floats are a digital representation of a number with - of course - an error margin. You don’t have the infinite precision with a digital number you need to work with floats... – patrick Jul 21 '18 at 16:59
  • More reading: https://msdn.microsoft.com/en-us/library/c151dt3s.aspx – patrick Jul 21 '18 at 17:00
  • Hey Patrick, thank you for the quick response! However, I'm not quite sure what you mean here. Additionally, the article furthers my understanding that floating point precision is the issue, but I'm not quite sure how to approach the problem(specifically in php as well) – Darthmaul Jul 21 '18 at 17:17
  • You need to install/enable the bcmath extension. Most hosts should have this enabled. – Devon Bessemer Jul 21 '18 at 17:17
  • After getting BC Math working on my setup, I am greeted with the exact same result here. So I don't think BC Math is the right approach here unfortunately :( – Darthmaul Jul 21 '18 at 17:55
  • This is related to a **rounding behavior** on prices calculations, but not to PHP floating point precision in Wordpress… So you should search about rounding behavior in Woocommerce. I had a similar problem once and replacing `number_format()`, with `round()` solved the problem (but not sure it will do the trick for you)… – LoicTheAztec Jul 21 '18 at 17:56
  • Thanks for the suggestion Loic, unfortunately even with `round()` I am still .01 off on my calculations. I am looking into solutions regarding general Woocommerce rounding. Thanks – Darthmaul Jul 21 '18 at 18:03
  • The problem with the code in your question is that is not really testable to be able to reproduce your issue… Remember that *"Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error **and the shortest code necessary to reproduce it in the question itself."*** … So you should try to add all necessary code in your question, to make that really testable. – LoicTheAztec Jul 21 '18 at 19:01
  • Hey, thank you for the continued support here. After reading everyone's suggestions and all the comments, I don't think there's a solution anyone could help me arrive at. I think this is more of a language/platform consideration thing and I need to probably look into other ways of accomplishing what I'm doing. – Darthmaul Jul 21 '18 at 19:07

0 Answers0