From: FAQ server on
-----------------------------------------------------------------------
FAQ Topic - How do I format a Number as a String with
exactly 2 decimal places?
-----------------------------------------------------------------------

When formatting money for example, to format 6.57634 to 6.58, 6.7 to
6.50, and 6 to 6.00?

Rounding of x.xx5 is unreliable, as most numbers are not represented
exactly. See also:
Why does simple decimal arithmetic give strange results? [ref 1]

The statement `n = Math.round(n * 100)/100` converts `n` to a `Number` value
close to a multiple of `0.01`. However, there are some problems.
Converting the number to a string `(n + "")`, does not give
trailing zeroes. Rounding numbers that are very close to `x.5`, for example,
`Math.round(0.49999999999999992)` results `1`.

ECMA-262 3rd Edition introduced `Number.prototype.toFixed`.
There are bugs in JScript's implementation with certain numbers,
for example `0.07`.

var numberToFixed =
(function() {
return toFixedString;

function toFixedString(n, digits) {
var unsigned = toUnsignedString(Math.abs(n), digits);
return (n < 0 ? "-" : "") + unsigned;
}

function toUnsignedString(m, digits) {
var t, s = Math.round(m * Math.pow(10, digits)) + "",
start, end;
if (/\D/.test(s)) {
return "" + m;
}
s = padLeft(s, 1 + digits, "0");
start = s.substring(0, t = (s.length - digits));
end = s.substring(t);
if(end) {
end = "." + end;
}
return start + end; // avoid "0."
}
/**
* @param {string} input: input value converted to string.
* @param {number} size: desired length of output.
* @param {string} ch: single character to prefix to s.
*/
function padLeft(input, size, ch) {
var s = input + "";
while(s.length < size) {
s = ch + s;
}
return s;
}
})();

// Test results
document.writeln([
"numberToFixed(9e-3, 12) => " + numberToFixed(9e-3, 12),
"numberToFixed(1.255, 2) => " + numberToFixed(1.255, 2),
"numberToFixed(1.355, 2) => " + numberToFixed(1.355, 2),
"numberToFixed(0.1255, 3) => " + numberToFixed(0.1255, 3),
"numberToFixed(0.07, 2) => " + numberToFixed(0.07, 2),
"numberToFixed(0.0000000006, 1) => " + numberToFixed(0.0000000006, 1),
"numberToFixed(0.0000000006, 0) => " + numberToFixed(0.0000000006, 0)
].join("\n"));

<URL: http://www.merlyn.demon.co.uk/js-round.htm>
<URL: http://msdn.microsoft.com/en-us/library/sstyff0z%28VS.85%29.aspx>

References:
-----------

[1] http://jibbering.com/faq/#binaryNumbers


The complete comp.lang.javascript FAQ is at
http://jibbering.com/faq/

--

The sendings of these daily posts are proficiently hosted
by http://www.pair.com.

From: Ry Nohryb on
On Jul 28, 1:00 am, "FAQ server" <javascr...(a)dotinternet.be> wrote:
> -----------------------------------------------------------------------
> FAQ Topic - How do I format a Number as a String with
> exactly 2 decimal places?
> -----------------------------------------------------------------------
> (...)

This is the problem. JavaScript coding style bent to suit IE's bugs.
NO, please, no. The proper way to do this is :

(number).toFixed(decimalPlaces) --> string

For example:

Math.PI.toFixed(3)
"3.142"

or

(6).toFixed(2)
--> "6.00"

That's what ought to come FIRST in this FAQ entry, and it should be
the recommended way of doing it.

Then, -*only*after*having*said*that*in*the*first*place*-, you can also
say that IEs have got (yet another) bug that affects
Number.prototype.toFixed(), sooo, in IEs you could do instead:

(blah, blah, blah)
--
Jorge.
From: David Mark on
On Jul 28, 12:16 pm, kangax <kan...(a)gmail.com> wrote:
> On 7/27/10 7:24 PM, Ry Nohryb wrote:
>
>
>
>
>
> > On Jul 28, 1:00 am, "FAQ server"<javascr...(a)dotinternet.be>  wrote:
> >> -----------------------------------------------------------------------
> >> FAQ Topic - How do I format a Number as a String with
> >> exactly 2 decimal places?
> >> -----------------------------------------------------------------------
> >> (...)
>
> > This is the problem. JavaScript coding style bent to suit IE's bugs.
> > NO, please, no. The proper way to do this is :
>
> > (number).toFixed(decimalPlaces) -->  string
>
> > For example:
>
> > Math.PI.toFixed(3)
> > "3.142"
>
> > or
>
> > (6).toFixed(2)
> > -->  "6.00"
>
> > That's what ought to come FIRST in this FAQ entry, and it should be
> > the recommended way of doing it.
>
> > Then, -*only*after*having*said*that*in*the*first*place*-, you can also
> > say that IEs have got (yet another) bug that affects
> > Number.prototype.toFixed(), sooo, in IEs you could do instead:
>
> > (blah, blah, blah)
>
> Does `numberToFixed` from the FAQ entry solve anything that fully
> compliant `Number.prototype.toFixed` doesn't? From what I can see, they
> should be identical.

Haven't looked at it. Will check when I have a chance.

>
> If they are, then why not employ a feature test and skip workaround once
> implementation is determined to be compliant? At least for performance
> reasons.
>

I've got one here somewhere. In my branch of Dojo I think (replaced a
UA sniff for IE). :)
From: Dr J R Stockton on
In comp.lang.javascript message <4c4f64f9$0$279$14726298(a)news.sunsite.dk
>, Tue, 27 Jul 2010 23:00:03, FAQ server <javascript(a)dotinternet.be>
posted:


>FAQ Topic - How do I format a Number as a String with
>exactly 2 decimal places?


>ECMA-262 3rd Edition introduced `Number.prototype.toFixed`.
>There are bugs in JScript's implementation with certain numbers,
>for example `0.07`.

No, there is no bug with toFixed formatting 0.07 as per Subject.

0.07.toFixed(2) -> '0.07'

You have been told, more than once IIRC, and have agreed at least once,
that the example should be 0.007 or similar.

NOW is the time to make the correction.

There is, in addition, a bug in Opera's toPrecision :

0.1230.toPrecision(4) -> 0.123 // should be 0.1230


>function toFixedString(n, digits) {
>var unsigned = toUnsignedString(Math.abs(n), digits);
>return (n < 0 ? "-" : "") + unsigned;
>}

That will not give the correct sign for n == -0 .

In the FAQ, sign should be given by a function such as

function Sign(X) { return X>0 ? "+" : X<0 ? "-" : " " }

Readers can more easily simplify that where needed than they can add to
the simplistic form in the FAQ.

There should also be a mention of testing the sign of (X+1/X).

--
(c) John Stockton, nr London UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
Proper <= 4-line sig. separator as above, a line exactly "-- " (RFCs 5536/7)
Do not Mail News to me. Before a reply, quote with ">" or "> " (RFCs 5536/7)
From: David Mark on
On Jul 29, 3:57 pm, Dr J R Stockton <reply1...(a)merlyn.demon.co.uk>
wrote:
> In comp.lang.javascript message <k-idncXl5612ys3RnZ2dnUVZ_rqdnZ2d(a)gigane
> ws.com>, Wed, 28 Jul 2010 12:16:43, kangax <kan...(a)gmail.com> posted:
>
> >Does `numberToFixed` from the FAQ entry solve anything that fully
> >compliant `Number.prototype.toFixed` doesn't? From what I can see, they
> >should be identical.
>
> In FF 3.0.19 and IE8, (-0).toFixed(2) wrongly gives '0.00'.  The code in
> the FAQ could be corrected to fix that too.
>
> >If they are, then why not employ a feature test and skip workaround
> >once implementation is determined to be compliant? At least for
> >performance reasons.
>
> Using a feature test means that the code must be tested in at least two
> browsers.  It means that more code must be downloaded.
>
> And, considering the likely usage as being for display (or for writing
> to file with WSH JScript), does speed matter?
>
> Doing StrS(Math.PI, 3, 5) on this machine takes under 24 us in FireFox,
> and StrS is similar to the FAQ code; doing Math.PI.toFixed(5) takes
> under 4 us.  Will that 20 us difference matter significantly often?

As always, it depends on the context. That's one of the problems
inherent to writing GP code.