Velocity Reviews > FAQ Topic - How do I convert a Number into a String with exactly 2 decimal places? (2008-06-20)

# FAQ Topic - How do I convert a Number into a String with exactly 2 decimal places? (2008-06-20)

FAQ server
Guest
Posts: n/a

 06-19-2008
-----------------------------------------------------------------------
FAQ Topic - How do I convert a Number into a String with
exactly 2 decimal places?
-----------------------------------------------------------------------

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

Rounding of x.xx5 is uncertain, as such numbers are not
represented exactly. See section 4.7 for Rounding issues.

N = Math.round(N*100)/100 only converts N to a Number of value
close to a multiple of 0.01; but document.write(N) does not give
trailing zeroes.

ECMAScript Ed. 3.0 (JScript 5.5 [but buggy] and JavaScript 1.5)
introduced N.toFixed, the main problem with this is the bugs in
JScripts implementation.

Most implementations fail with certain numbers, for example 0.07.
The following works successfully for M>0, N>0:

function Stretch(Q, L, c) { var S = Q
if (c.length>0) while (S.length<L) { S = c+S }
return S
}
function StrU(X, M, N) { // X>=0.0
var T, S=new String(Math.round(X*Number("1e"+N)))
if (S.search && S.search(/\D/)!=-1) { return ''+X }
with (new String(Stretch(S, M+N, '0')))
return substring(0, T=(length-N)) + '.' + substring(T)
}
function Sign(X) { return X>0 ? "+" : X<0 ? "-" : " " }
function StrS(X, M, N) { return Sign(X)+StrU(Math.abs(X), M, N) }
Number.prototype.toFixed = function(n){ return StrS(this,1,n) };

http://www.merlyn.demon.co.uk/js-round.htm

http://msdn2.microsoft.com/en-us/library/sstyff0z.aspx

--
Postings such as this are automatically sent once a day. Their
goal is to answer repeated questions, and to offer the content to
the community for continuous evaluation/improvement. The complete
comp.lang.javascript FAQ is at http://jibbering.com/faq/index.html.
The FAQ workers are a group of volunteers. The sendings of these
daily posts are proficiently hosted by http://www.pair.com.

Evertjan.
Guest
Posts: n/a

 06-20-2008
FAQ server wrote on 20 jun 2008 in comp.lang.javascript:

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

function round(n,d){
n = Math.floor(n*Math.pow(10,d)+.5);
if (d<1) return n;
var s = Math.abs(n).toString();
while (s.length<d+1) s = '0' + s;
return ((n<0) ?'-':'') + s.slice(0,-d) + '.' + s.slice(-d);
};

I do not trust internal rounding to be according to my definition.
I like the slice() string manpulation possibilities.

Shoot?

--
Evertjan.
The Netherlands.

yukabuk
Guest
Posts: n/a

 06-20-2008
You should write this...

var numberObj = new Number(6.57634);
var formattedNumber = numberObj.toFixed(2);

Graham

Evertjan.
Guest
Posts: n/a

 06-20-2008
yukabuk wrote on 20 jun 2008 in comp.lang.javascript:

> You should write this...
>
> var numberObj = new Number(6.57634);
> var formattedNumber = numberObj.toFixed(2);

You? Why?

What are you responding on?

--
Evertjan.
The Netherlands.

Dr J R Stockton
Guest
Posts: n/a

 06-20-2008
In comp.lang.javascript message <Xns9AC39D119DD31eejj99@194.109.133.242>
, Fri, 20 Jun 2008 13:26:35, Evertjan. <(E-Mail Removed)>
posted:
>FAQ server wrote on 20 jun 2008 in comp.lang.javascript:
>
>> -----------------------------------------------------------------------
>> FAQ Topic - How do I convert a Number into a String with
>> exactly 2 decimal places?
>> -----------------------------------------------------------------------

>

Fails, I think, for n=1.11, d>21 ; also for n = infinity, NaN. Put your
function, followed by return round(X, N) in the second textarea of
<URL:http://www.merlyn.demon.co.uk/js-round.htm#TRPF> and press the
button.

>function round(n,d){
> n = Math.floor(n*Math.pow(10,d)+.5);
> if (d<1) return n;
> var s = Math.abs(n).toString();
> while (s.length<d+1) s = '0' + s;
> return ((n<0) ?'-':'') + s.slice(0,-d) + '.' + s.slice(-d);
>};
>
>I do not trust internal rounding to be according to my definition.
>I like the slice() string manpulation possibilities.
>
>Shoot?

The one in the FAQ includes provision for a fixed number of places, or
characters, before the decimal separator, which is useful for tables in
<pre>, etc.

It would be nicer, for those who recall FORTRAN convention, to use x
instead of n. And, to please IUPAP/SUNAMCO. .5 should be 0.5 .

Note that I don't use what the FAQ says.

--
(c) John Stockton, nr London UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.merlyn.demon.co.uk/clpb-faq.txt> RAH Prins : c.l.p.b mFAQ;
<URL:ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ.

Evertjan.
Guest
Posts: n/a

 06-21-2008
Dr J R Stockton wrote on 20 jun 2008 in comp.lang.javascript:

>
> Fails, I think, for n=1.11, d>21 ; also for n = infinity, NaN.

With quoted 'any', I ment any reasonable.

Catching all possibilities makes the code sound but unreadable for
instruction.

> Put your
> function, followed by return round(X, N) in the second textarea of
> <URL:http://www.merlyn.demon.co.uk/js-round.htm#TRPF> and press the
> button.

Sorry, John, your server seems down.

--
Evertjan.
The Netherlands.

Dr J R Stockton
Guest
Posts: n/a

 06-21-2008
On Jun 21, 8:53*am, "Evertjan." <(E-Mail Removed)> wrote:
> Dr J R Stockton wrote on 20 jun 2008 in comp.lang.javascript:
>

>
> > Fails, I think, for n=1.11, d>21 ; also for n = infinity, NaN. *

>
> With quoted 'any', I ment any reasonable.
>
> Catching all possibilities makes the code sound but unreadable for
> instruction.

It is only necessary to include a test that s is all-digit, such as
if (/\D/.test(d)) return n // cannot cope

IMHO, d=0 should be allowed; it should give results such as "3." which
is deprecated but not wrong.

> Sorry, John, your server seems down.

<QUOTE>
We will be carrying out planned maintenance of our Web Hosting
platform as follows:
Saturday 21st June between 00:01 and 20:00 Hrs BST
Saturday 28th June between 00:01 and 04:00 Hrs BST
Sunday 29th June between 00:01 and 04:00 Hrs BST
</QUOTE>

--
(c) John Stockton, near London, UK. Posting with Google.
Web: <URL:http://www.merlyn.demon.co.uk/>
FAQish topics, acronyms, links, etc.; Date, Delphi, JavaScript, ...

dhtml
Guest
Posts: n/a

 06-21-2008
On Jun 19, 4:00*pm, "FAQ server" <(E-Mail Removed)> wrote:

[snip]

> ECMAScript Ed. 3.0 (JScript 5.5 [but buggy] and JavaScript 1.5)
> introduced N.toFixed, the main problem with this is the bugs in
> JScripts implementation.
>

The other problem is that internal representation and handling with
binary numbers leads to unintuitive results that seem wrong.

toFixed calls internal ToNumber which calls internal ToInteger, to get
the exact mathematical value of the number. This is then rounded to a
value of the Number type.

This is why Mozilla will give 1.1255.toFixed(3) => 1.125

1.125499999999999944932937978592235594987869262695 3125)

Method toFixed is pretty much useless.

[snip]

Garrett

> --

Richard Cornford
Guest
Posts: n/a

 06-21-2008
dhtml wrote:
>On Jun 19, 4:00 pm, FAQ server wrote:
>[snip]
>> ECMAScript Ed. 3.0 (JScript 5.5 [but buggy] and JavaScript 1.5)
>> introduced N.toFixed, the main problem with this is the bugs in
>> JScripts implementation.

>
> The other problem is that internal representation and handling
> with binary numbers leads to unintuitive results that seem wrong.

The only factor in making binary number handling non-intuitive is that
most human intuition is heavily influenced by our use habitual of
decimal numbers. Decimal numbers have exactly the same issues in reality
(the decimal representation of 1 divided by 3, for example, is going to
imprecise or impractical), it is just the issues appear in unfamiliar
locations (with unfamiliar values).

> toFixed calls internal ToNumber which calls internal ToInteger,
> to get the exact mathematical value of the number. This is then
> rounded to a value of the Number type.

Wouldn't it be a good idea to look at the specification before making
assertions like this? The algorithm for - toFixed - does not call
ToNumber at all and it only calls ToInteger on the value that is its
argument (the "fractionDigits" value).

> This is why Mozilla will give 1.1255.toFixed(3) => 1.125

> 1.125499999999999944932937978592235594987869262695 3125)

> Method toFixed is pretty much useless.

You may be attributing an issue to the wrong part of the process.
Remember that a numeric literal in source code must be translated into
an internal number value that is an IEEE double precision floating point
number, and that not all values that can be represented as a precise
decimal value can also be precisely represented as an IEEE double
precision floating point number. If you code the numeric literal
"1.1255" and it is translated into the nearest available IEEE double
precision floating point number representation then that happens at the
compiling stage (or thereabouts) so you shouldn't fault - toFixed - for
correctly handling that approximate value when it acts at runtime.

Richard.

dhtml
Guest
Posts: n/a

 06-22-2008
On Jun 21, 11:10 am, "Richard Cornford" <(E-Mail Removed)>
wrote:
> dhtml wrote:
> >On Jun 19, 4:00 pm, FAQ server wrote:

>
> > toFixed calls internal ToNumber which calls internal ToInteger,
> > to get the exact mathematical value of the number. This is then
> > rounded to a value of the Number type.

>
> Wouldn't it be a good idea to look at the specification before making
> assertions like this? The algorithm for - toFixed - does not call
> ToNumber at all and it only calls ToInteger on the value that is its
> argument (the "fractionDigits" value).
>

Right.

toFixed calls ToInteger, which calls ToNumber.

> Richard.