views:

1391

answers:

8

I need to round decimal numbers to six places using JavaScript, but I need to consider legacy browsers so I can't rely on Number.toFixed

The big catch with toExponential, toFixed, and toPrecision is that they are fairly modern constructs not supported in Mozilla until Firefox version 1.5 (although IE supported the methods since version 5.5). While it's mostly safe to use these methods, older browsers WILL break so if you are writing a public program it's recommended you provide your own prototypes to provide functionality for these methods for older browser.

I'm considering using something like

Math.round(N*1000000)/1000000

What is the best method for providing this a prototype to older browsers?

A: 

I think Firefox 1.5 and IE 5 are pretty much no longer used, or by a very minor quantity of people.
It is a bit like coding to support Netscape Navigator... :-)
Unless some other major browser (Opera? Safari? unlikely...) doesn't support this, or if your Web logs show lot of legacy browser use, you can probably just use these methods.
Sometime, we have to move on. ^_^

[EDIT] Works fine on Opera 9.50 and Safari 3.1

javascript: var num = 3.1415926535897932384; alert(num.toFixed(7));

The article you reference is a year and half ago, an eternity in IT industry... I think that, unlike IE users, Firefox users often go to the latest version.

PhiLho
+6  A: 
Sergey Ilinsky
A: 

From Bytes website, this function is almost the same than Serge llinsky's:

if (!num.toFixed) 
{
  Number.prototype.toFixed = function(precision) 
  {
     var num = (Math.round(this*Math.pow(10,precision))).toString();
     return num.substring(0,num.length-precision) + "." + 
            num.substring(num.length-precision, num.length);
  }
}
VonC
+1  A: 

We encountered an issue where IE7 and Firefox 3 rendered the result of toFixed differently.

In IE: 0.00633633 toFixed(2) gave 0.00 (how wrong is that!!)

In Firefox: 0.00633633 toFixed(2) gave 0.01 (which is correct)

In this case the answer from Sergey is the solution we'll be using.

A: 

Another option is ( which doesn't convert to a string unnecessarily, and also corrects the miscalculation of (162.295).toFixed(2) to 162.29 ( should be 162.30 )).

Number.prototype._toFixed=Number.prototype.toFixed; //Preserves the current function
Number.prototype.toFixed=function(precision){
/* step 1 */ var a=this, pre=Math.pow(10,precision||0);
/* step 2 */ a*=pre; //currently number is 162295.499999
/* step 3 */ a = a._toFixed(2); //sets 2 more digits of precision creating 16230.00
/* step 4 */ a = Math.round(a);
/* step 5 */ a/=pre;
/* step 6 */ return a._toFixed(precision);
}
/*This last step corrects the number of digits from 162.3 ( which is what we get in
step 5 to the corrected 162.30. Without it we would get 162.3 */

Edit: Upon trying this specific incarnation, this*=Math.pow(10, precision||0) creates an error invalid left-hand assignment. So gave the this keyword the variable a. It would also help if I closed my functions ^_^;;

A: 

Number.prototype.toFixed = function(precision) { var num = (Math.round (this*Math.pow(10,precision))).toString(); return (num.substring (0,num.length-precision)||"0") + "." + num.substring(num.length-precision, num.length); }

macem
A: 

Above function is incorrect please test 20/30000

This is correct: # Number.prototype.toFixed = function(precision) { # var power = Math.pow(10, precision || 0); # return String(Math.round(this * power)/power); # }

macem
A: 

I'm not sure that any of the implementations offered here are very good, do they not all suffer from floating point representation problems?

David Roe
Can you explain what you mean, ideally with code samples?
Ken
I can give a set of inputs that show what I mean. But to really understand the problem you need to learn about floating point. The issue in that implementation is that it multiplies+divides by a floating point number. Try with number "23456789999999991" and precision "-1" and compare to the browser implementation. In fact, I was in error before by suggesting one of the other implementations on this page, they all seem to suffer from this problem.
David Roe
Further investigation suggests that the example I gave isn't very good, not sure the number itself is representable exactly. I still feel like there is a problem though, unless the precision cancels out somehow?
David Roe