There was the following problem. Need a function to round the number to hundredths in a big way. Initially, the function was as follows:

function round_up($value, $precision) { $pow = pow ( 10, $precision ); return ceil($value * $pow) / $pow; } 

but there was a problem when passing the next round_up(740*0.006,2) value to the round_up(740*0.006,2) it gives 4.45 instead of 4.44. Further, the function is corrected in the following form:

 function round_up ( $value, $precision ) { $pow = pow ( 10, $precision ); return ceil(round($value * $pow,2)) / $pow; } 

solved the previous problem, but a new one also arose when passing to the function of the next value:

 round_up(3208.34*0.006,2) 

it gives out 19.25 instead of 19.26. Who can already faced it? Thanks a lot in advance!!!

  • one
    tl; dw: the number with a comma has a finite accuracy that you are resisting. The easiest way is to use the number_format() function. - etki 2:51 pm
  • I tried your version, the same thing: $ num = 3208.34 * 0.006; echo number_format ($ num, 2, '.', ''). '<br>'; Result 19.25 - Alex Kulinenko
  • Yes, without rounding, we get this value, but I base on the value obtained from Microsoft Excel, this is where the operation after passing through the ceiling function yields 19.26. - user179235
  • I thought and thought and did not invent anything (good). In principle, your initial idea is correct, but it is hampered by the fact that the resulting number may be slightly more than expected. There are several options, all are bad, but the essence is approximately as follows: either the string representations of the number "before" and "after" are compared, or some one hundred thousandth is taken away from the number in the hope that it eliminates the accuracy of the float. When I worked in the same project with a mobile operator, they scored there and all the calculations were done in numbers, 10,000 times more real. - etki
  • function round_up ($ num, $ precision) {$ pow = pow (10, $ precision); return ceil ($ num * $ pow - 0.00000000001) / $ pow; } now this option has been made on the old version of php, maybe it will be useful to someone. Php version 5.2.14. Thank you, Etki - Alex Kulinenko

3 answers 3

Try this:

 function round_up ( $value, $precision ) { $pow = pow ( 10, $precision ); return round($value * $pow + 0.49999999999) / $pow; } 

Then, the first function given by you works correctly, but the error arises because of an error of calculations. I think that pow ( 10, 2.0 ) will not give out exactly 100, but something like 100.000001 If you need to round strictly up to 2 characters, try

 function round_up($value) { return ceil($value * 100) / 100; } 
  • Try this: function round_up ($ value, $ precision) {$ pow = pow (10, $ precision); return round ($ value * $ pow + 0.49999999999) / $ pow; } Tried, gives the desired value of 19.26; The same value is given by the first version of the function, which I indicated in the question, but when you substitute the value 740 * 0.006 into your example, the result is 4.45, and you need 4.44. - user179235
  • This option has tried since the beginning. Stumbled upon this article: stackoverflow.com/questions/7825321 / ... I thought that the ceil function does not quite correctly perceive the type of float, this is the last thing I tried: function round_up ($ value) {return ceil ($ value) / 100; } $ num = (int) (3208.34 * 0.006 * 100); echo round_up ($ num, 2); The result is 19.25; with a substitution of 740 * 0.006 * 100, it yields 4.44, as it should be. In general, I can not understand how it is considered in Excel. = CIRCLE UP (3208.34 * 0.006; 2) gives out 19.26 - Alex Kulinenko
  • function round_up ($ value) {return ceil ($ value) / 100; } $ num = (int) (3208.34 * 0.006 * 100); echo round_up ($ num, 2); - Tunker
  • Understood the error, but mistakenly passed the second parameter did not affect the overall picture .. - Alex Kulinenko
  • function round_up ($num, $precision) { $pow = pow(10, $precision); return round($num * $pow + 0.49999999999)/$pow; } function round_up ($num, $precision) { $pow = pow(10, $precision); return round($num * $pow + 0.49999999999)/$pow; } gives out 19.26 and 4.44 - Tunker

Sorry, are you trying to create a new rounding method? Why is 3208.34 * 0.006 supposed to give 19.26? If the result without rounding is 19,25004. I recommend that you familiarize yourself with the existing generally accepted rounding rules, because you use the ceil function in your function, which is based on rounding rules. And if you are trying to use a rule that you invent yourself, then here you will have to completely rewrite your rounding algorithm.

  • it is used in the above example - etki
  • I meant that according to the rounding rules 19.25004 = 19.25, but not 19.26, since when rounding up to hundredths (two decimal places), the “influence” has only the 3rd sign, i.e. the digit 0 after 5, and all other numbers are simply discarded (not taken into account at all). Apparently, the author is trying to round off in stages, which is not allowed according to rounding rules. Therefore, I proposed to get acquainted with the rules of rounding. - Vasil Baymurzin
  • amend the question. Rounding up suggests 19.26 - Yevgeny Borisov
  • If you round up to the top, then 19.25004 = 19.2501 = 19.251 = 19.26, then yes. But according to the rules, SO is not rounded, even when choosing the rounding method "to the top". When rounding, insignificant digits are generally discarded, i.e. 19,250 = 19.25, and 0.00004, is not considered at all. And these rules apply to all built-in functions. Google "Rounding Rules" - Vasil Baymurzin
  • @VasilBaymurzin, that is, according to your theory, rounding up in Microsoft Excel, also in the ACN Bank, where the ceiling function is used is not performed according to the rounding rules ?? oh well .. - Alex Kulinenko

The main problem with floating point numbers is that their internal representation may differ, and almost always differs from decimal. I mean initially, they are often irrational numbers in the decimal representation.

The solution of the problem (rounding up, positive numbers) - roughly rounding down, then comparing the result with the source. If the difference between the source and rounding is greater than zero, then add a significant unit to the result.

 function round_up ($ number, $ digits = 2) {
     $ limit = pow (0.1, $ digits);  // significant unit.  default 0.01
     $ pow_limit = pow (10, $ digits);  // reverse value.  default 100
     $ floor_nl = floor ($ number * $ pow_limit) / $ pow_limit;  // rough rounding
     $ need_up = (($ number - $ floor_nl)> 0);  // flag, do I need increment.

     if ($ need_up) {$ floor_nl + = $ limit;  }
     return $ floor_nl; 
 } 

To account for negative numbers, you must add the appropriate check.

  • Your option checked, the decision is actually very good !! Thank!! Negative numbers in my case are not needed, since this is a calculation of the commission on payments .. - Alex Kulinenko
  • I checked the work on some amounts of operations, they also include problem ones ... everything worked perfectly! - Alex Kulinenko