0

I'm doing some calculations on both client and server, and I've found a difference in the final result.

What am I doing wrong and what would be the correct way for obtaining a 2 decimal float for representing currency.

Consider the following code (final number without format is 1,785):

JS

var sum = parseFloat(8.50);
var tax = parseFloat(21.00);
var total = parseFloat(sum * (tax / 100));
var test = total.toFixed(2);
console.log(test);

PHP

$sum = (float)"8.50";
$tax = (float)"21.00";
$total = (float)($sum * ($tax / 100));
$test = number_format($total, 2, ".", "");
echo $test;

In JS I get 1.78 and in PHP 1.79

Matías Cánepa
  • 5,770
  • 4
  • 57
  • 97
  • you should make the title a bit more clear. **format currency in PHP and JavaScript** suggests that you want a method which works with currencies, but in question you ask why different parsing/number formatting methods return different results. consider changing the title to something like ***why does different PHP and JS format numbers differently*** – Minato Aug 03 '18 at 22:48
  • if your question is only working with currencies/formatting currencies, @HorusKol gave you the perfect answer. – Minato Aug 03 '18 at 22:51

4 Answers4

1

JS

var sum = parseFloat(8.50);
var tax = parseFloat(21.00);
var total = Math.round(sum*tax) / 100;

PHP

$sum = (float)"8.50";
$tax = (float)"21.00";
$total = round($sum*$tax/100, 2);

The mathematically correct rounding for 1.785 is 1.79 so the code above gives you what you want.

iiirxs
  • 4,493
  • 2
  • 20
  • 35
  • its not mathematically correct rounding, mathematically correct is 1.78 – Minato Aug 03 '18 at 22:29
  • Do your research sir! – iiirxs Aug 03 '18 at 22:30
  • I know and just confirmed xD, 5 only updates the odd digits* on the left – Minato Aug 03 '18 at 22:31
  • common dude we are working with floats here. The convention you share is rounding 1.25 to 1, in the first example. – Minato Aug 03 '18 at 22:38
  • No need to argue. Just study your math. In this example it was the ceiling function. W/e learn also the notations – iiirxs Aug 03 '18 at 22:38
  • believe me I've studied my fair share of maths and Computer Science already. – Minato Aug 03 '18 at 22:39
  • well, ceiling and floor functions are only applicable to Real to Integers conversion. Rounding functions are more general, the take a float and return a float. in maths rounding function takes real and map to real, while ceil/floor takes Real and maps to Integer. – Minato Aug 03 '18 at 22:44
1

Possible duplicate of

You can use

function RoundNum(num, length) { 
    var number = Math.round(num * Math.pow(10, length)) / Math.pow(10, length);
    return number;
}
Michał B
  • 96
  • 10
1

You should not to use floats for storing and calculating currency values - use integers, with a resolution of 1/100 of a cent (or penny or whatever). Some financial applications go further - 1/10 000.

So, $1 is stored as 10 000 in your database.

After you have calculated taxes and totals, and rounded the result, then you can convert into a dollar amount for presentation.

var sum = 85000; // $8.50
var taxRate = 0.21; // 21%
var tax = sum * taxRate; // $1.785
console.log(Math.round(tax / 100) / 100); // $1.79

var cents = tax / 100; // 178.5 cents
var wholeCents = Math.round(cents); // 179 cents
var dollars = cents / 100; // $1.79
HorusKol
  • 8,375
  • 10
  • 51
  • 92
  • This is not answering my question at all – Matías Cánepa Aug 03 '18 at 22:35
  • nice answer, I have seen this convention nearly in all the codebases that I have worked with. Seems like an industry wide convention. – Minato Aug 03 '18 at 22:36
  • @MatíasCánepa I'm trying to save you the headache of imprecise floating point representation when trying to work with precise currency calculations – HorusKol Aug 03 '18 at 22:57
0

That's because PHP's number_format is rounding the numbers, if you don't want that, consider this function:

function numberFormatNotRound($n, $decs, $decPoint = '.', $thousandsSep = ',')
{
    $decs ++;
    $n = number_format($n, $decs, $decPoint, $thousandsSep);
    $n = substr($n, 0, -1);

    return $n;
}

PHPFiddle: http://phpfiddle.org/lite/code/457c-00nv

Luca Kiebel
  • 9,790
  • 7
  • 29
  • 44