Help ! Shopping Cart Problem

P

Phil McKraken

I am having a problem putting together a shopping cart with the below
script. Everything displays fine, adds totals fine, and works perfect
EXCEPT if you choose the 9.95 item #5 BY ITSELF the total displayed is
$9.94 ! If you add ANYTHING else the total is correct, 9.95 plus
whatever you add. That is the only price in these samples that is
doing that. All the others display properly. If you change the 9.95 to
ANY other number it displays correct. If you put 9.95 in any other
position (Item number 1 instead of 5 etc. it does the same thing)

Any ideas ? I am completely stumped. Please Help
TIA

(This is the entire html page you can paste it and view in a browser
to see the problem with the 9.95 item.)

<html><head>

<script language="JavaScript">
<!-- hide contents from old browsers

var Cost, Grand_Total;

function tally()
{
Cost = 0;
if (document.orderform.Item1.checked) { Cost = Cost + 119.95;
}
if (document.orderform.Item2.checked) { Cost = Cost + 75.00; }
if (document.orderform.Item3.checked) { Cost = Cost + 14.95; }
if (document.orderform.Item4.checked) { Cost = Cost + 50.00; }
if (document.orderform.Item5.checked) { Cost = Cost + 9.95; }
if (document.orderform.Item6.checked) { Cost = Cost + 4.95; }
if (document.orderform.Item7.checked) { Cost = Cost + 50.00; }
if (document.orderform.Item8.checked) { Cost = Cost + 7.95; }
if (document.orderform.Item9.checked) { Cost = Cost + 1.00; }

Cost = dollar(Cost);
Grand_Total = parseFloat(Cost)
Grand_Total = dollar(Grand_Total);

document.orderform.GrandTotal.value = "$" + Grand_Total;
}

function dollar (amount)
{
amount = parseInt(amount * 100);
amount = parseFloat(amount/100);
if (((amount) == Math.floor(amount)) && ((amount - Math.floor
(amount)) == 0))
{
amount = amount + ".00"
return amount;
}
if ( ((amount * 10) - Math.floor(amount * 10)) == 0)
{
amount = amount + "0";
return amount;
}
if ( ((amount * 100) - Math.floor(amount * 100)) == 0)
{
amount = amount;
return amount;
}
return amount;
}

//-->
</script>
</head>
<body><center>

<form method="post" name="orderform" action="mailto:[email protected]"
enctype="text/plain">
<table bgcolor="#EFEFEF" border="0" cellspacing="0"
cellpadding="3"><font face="verdana" size="1" color="#000000"><b>
<tr><td valign="top"><font face="verdana" size="2"
color="#000000"><b>
<p><input name="Item1" value="AcceleratedHighSpeedAnnual"
onclick="tally()" type="checkbox">Accelerated Dial-Up Internet Access
1 Year Pre-Pay ($119.95)
</p><p><input name="Item2" value="Item2_chosen" onclick="tally()"
type="checkbox"> Accelerated Dial Up Internet Access Semi-Annual
Pre-Pay ($75.00)
</p><p><input name="Item3" value="Item3_chosen" onclick="tally()"
type="checkbox"> Accelerated Dial Up Internet Access Monthly Billing
($14.95)
</p><p><input name="Item4" value="Item4_chosen" onclick="tally()"
type="checkbox"> Regular Dial Up Internet Access Semi-Annual Billing
($50.00)
</p><p><input name="Item5" value="Item5_chosen" onclick="tally()"
type="checkbox"> Regular Dial Up Internet Access Monthly Billing
($9.95)
</p></td><td valign="top"><font face="verdana" size="2"
color="#000000"><b>
</p><p><input name="Item6" value="Item6_chosen" onclick="tally()"
type="checkbox"> Add 3 Email Monthly Billing ($4.95)
</p><p><input name="Item7" value="Item7_chosen" onclick="tally()"
type="checkbox"> Add 3 Email 1 Year Pre-Pay ($50.00)
</p><p><input name="Item8" value="Item8_chosen" onclick="tally()"
type="checkbox"> 10 Email Only Monthly Billing Only (7.95)
</p><p><input name="Item9" value="Item9_chosen" onclick="tally()"
type="checkbox"> Mail Invoice for Payment by Check ($1.00)
<br><br><font color="red">Total Due: <input name="GrandTotal"
value="$0" size="8" type="text"></font>
</p></td></tr></table><br><br>
<center><input value="Send Order" type="submit"><input value="Reset
Order" type="reset"></center>
</form>
</body></html>
 
R

RobG

Phil said:
I am having a problem putting together a shopping cart with the below
script. Everything displays fine, adds totals fine, and works perfect
EXCEPT if you choose the 9.95 item #5 BY ITSELF the total displayed is
$9.94 ! If you add ANYTHING else the total is correct, 9.95 plus
whatever you add. That is the only price in these samples that is
doing that. All the others display properly. If you change the 9.95 to
ANY other number it displays correct. If you put 9.95 in any other
position (Item number 1 instead of 5 etc. it does the same thing)

Any ideas ? I am completely stumped. Please Help

The problem is your dollar() function, here is a link to some 'to money'
conversion stuff:

<URL:http://www.merlyn.demon.co.uk/js-maths.htm#Money>

Or search the group for money conversion functions, I'm sure there are a
couple of good ones that have been posted. There is an extensive thread
here:

<URL:http://groups.google.com/group/comp...c=1&q=convert+to+money&hl=en#df3038f5a0934436>


Converting strings to numbers and back using multiplication may result
in a rounded value that is not what you started with - 9.95 being a
'magic' number for your dollar function.

Use string manipulation for formatting numbers if you want to ensure
that they don't get modified.

[...]
 
P

Phil McKraken

The problem is your dollar() function, here is a link to some 'to money'
conversion stuff:

I tried the links you posted but, :) no luck. I am sure I am just
doing it wrong. I got this sample from one of those javascript web
repositories and I am not competent to change it to make it work. I am
still learning and am not really a js writer, only a "cut n paste"
trial & error modifier of what's there already.

Can someone tell me what to do to fix this a little more specifically.

Thanks for the responses. I really appreciate it. This is the way you
learn I guess.

When I tried the links, I screwed it up so bad it doesn't work at all
now. (Yes I have a backup that works the same as the original with the
"9.95" problem)

Thanks again.
 
R

Randy Webb

Phil McKraken said the following on 10/29/2005 12:03 PM:
I tried the links you posted but, :) no luck. I am sure I am just
doing it wrong. I got this sample from one of those javascript web
repositories and I am not competent to change it to make it work. I am
still learning and am not really a js writer, only a "cut n paste"
trial & error modifier of what's there already.

Can someone tell me what to do to fix this a little more specifically.

You are trying to round by multiplying by 100 and then dividing by 100.
That introduces the error you see because computers cannot represent
9.95 exactly in Base 2. So you get the error.

The way around that error is to convert your Number to a whole number,
do your calculations, and then add the decimal back with *String
Operations*. Meaning, you do not divide by 100, you convert it to a
String and then add the decimal.
 
L

Lee

Phil McKraken said:
I am having a problem putting together a shopping cart with the below
script. Everything displays fine, adds totals fine, and works perfect
EXCEPT if you choose the 9.95 item #5 BY ITSELF the total displayed is
$9.94 ! If you add ANYTHING else the total is correct, 9.95 plus
whatever you add. That is the only price in these samples that is
doing that. All the others display properly. If you change the 9.95 to
ANY other number it displays correct. If you put 9.95 in any other
position (Item number 1 instead of 5 etc. it does the same thing)

Any ideas ? I am completely stumped. Please Help

That's really just horrible code, and should be thrown away,
but the simplest fix to your problem is to remove the line
indicated below. Every time you call that ridiculous dollar()
function you introduce more error, so don't call it without
any reason. There's also no reason to use either parseFloat()
or parseInt() in this code, but at least they're not causing
the problem.
 
P

Phil McKraken

That's really just horrible code, and should be thrown away,
but the simplest fix to your problem is to remove the line
indicated below. Every time you call that ridiculous dollar()
function you introduce more error, so don't call it without
any reason. There's also no reason to use either parseFloat()
or parseInt() in this code, but at least they're not causing
the problem.

I appreciate the help and the sentiment regarding the code. I guess I
will have to find another one. I DID remove the line you suggested but
ALSO had to remove the "dollar" reference in the 2nd line down, with
Grand_Total.

Doing that caused the 9.95 and other **.95 items to display and add
ok. BUT, when you add ANY **.95 item to anything else (resulting in a
total that ends in "0" it drops off the "0".

I'm just not understanding enough of js yet to trouble shoot this.

Anyone know a better one ?

Thanks
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated
Sat, 29 Oct 2005 12:36:50, seen in Phil
McKraken said:
I am having a problem putting together a shopping cart with the below
script. Everything displays fine, adds totals fine, and works perfect
EXCEPT if you choose the 9.95 item #5 BY ITSELF the total displayed is
$9.94 ! If you add ANYTHING else the total is correct, 9.95 plus
whatever you add. That is the only price in these samples that is
doing that. All the others display properly. If you change the 9.95 to
ANY other number it displays correct.

You have tried all other numbers? For me, 19.65 gives 19.64.
If you put 9.95 in any other
position (Item number 1 instead of 5 etc. it does the same thing)

Any ideas ? I am completely stumped. Please Help

Read the newsgroup FAQ and what it cites.

Your conversion method, as well as being wrong, appears unnecessarily
large and slow. Delete your function "dollar"; euthanasia is the
kindest treatment for it.

Most scripts in Web repositories are trash; many are also bloatware.
 
R

RobG

Phil said:
I tried the links you posted but, :) no luck. I am sure I am just
doing it wrong. I got this sample from one of those javascript web
repositories and I am not competent to change it to make it work. I am
still learning and am not really a js writer, only a "cut n paste"
trial & error modifier of what's there already.

Can someone tell me what to do to fix this a little more specifically.

You really need to understand what the functions are doing and how they
work, else you will get errors like you have now. I hope you are
validating everything back at the server and only using the shopping
cart for advice to customers.

Anyhow, here's a couple of functions that may suit. They do no
validation at all and expect you to pass them suitable input. The first
expects to get dollars and never more than two decimal places, the
second expects integer cents.



<html><head><title>Play</title>

<script type="text/javascript">

// This function expects to get dollars as either an integer
// or a float but never more than 2 decimal places
function toDollars(amt)
{
if (0 == amt) return '0.00';
amt += ''; // Convert amt to string
amt = amt.split('.');
if (1 == amt.length) amt[1]='00';
if (0 == amt[1].length) amt[1] += '00';
if (1 == amt[1].length) amt[1] += '0';
return amt.join('.');
}

// This function expects to get only integer cents
function centsToDollars(amt)
{
amt += ''; // Convert amt to string
if (1 == amt.length) return '0.0'+ amt;
if (2 == amt.length) return '0.'+ amt;
var dollars = amt.substring(0,amt.length-2);
var cents = amt.substring(amt.length-2);
return dollars + '.' + cents;
}

</script>
</head><body>
Play with toDollars<br>
<input type="text" onblur="
this.value = toDollars(this.value);
"><br>
Play with centsToDollars<br>
<input type="text" onblur="
this.value = centsToDollars(this.value);
">

</body></html>


[...]
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Sat, 29 Oct
2005 13:45:09, seen in Randy Webb
You are trying to round by multiplying by 100 and then dividing by 100.
That introduces the error you see because computers cannot represent
9.95 exactly in Base 2. So you get the error.

Non sequitur.

If the representation of 9.95, while not exact, had sufficient zeroes at
the end of the mantissa, then the multiplication would be exact, and the
division would be exact and would give the original value. There,
"sufficient zeroes" is a sufficient, but probably not entirely
necessary, condition.

If 9.95 being represented inexactly were the only criterion, then ISTM
that one would expect more wrong results than the OP's code actually
gives.


The real problem is that the OP's type of method effectively truncates
to cents using an inexact input; the input must be rounded to exact
cents, which has to be done into a representation where all such values
can be rendered exactly.

The ordinary conversions of a general Number to a String do that
rounding, as does the obvious one of the conversions to an integer Cent
number.

Note that one should always multiply or divide by 100 in preference to
dividing or multiplying by 0.01, since 100 is represented exactly but
0.01 is not.
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated
Sat, 29 Oct 2005 19:37:51, seen in Phil
McKraken said:
I appreciate the help and the sentiment regarding the code. I guess I
will have to find another one. I DID remove the line you suggested but
ALSO had to remove the "dollar" reference in the 2nd line down, with
Grand_Total.

Doing that caused the 9.95 and other **.95 items to display and add
ok. BUT, when you add ANY **.95 item to anything else (resulting in a
total that ends in "0" it drops off the "0".

I'm just not understanding enough of js yet to trouble shoot this.

Your lack of understanding is more fundamental. You do not understand
the properties of the IEEE Double type. You probably do not even
understand that you need to understand that.

Anyone know a better one ?

Read the newsgroup FAQ.

It should be obvious enough to you that conversion of a currency
variable to a currency string is quite commonly needed, and, therefore,
that if the language does not provide, in all versions, an obvious and
reliable way of doing it, then the information needed can very probably
be found in or via a newsgroup FAQ.

No-one with any sense will bother to copy out the version in the
newsgroup FAQ when the whole purpose of having a newsgroup FAQ is to
obviate the repeated asking of common questions.

Remember that at least 90% of the script on the web, especially that in
repositories and libraries, is trash (script in actual use tends to get
debugged). Read the newsgroup FAQ.

Don't forget to read the newsgroup FAQ.
 
D

Dr John Stockton

JRS: In article <4364ad27$0$20422$5a62ac22@per-qv1-newsreader-
01.iinet.net.au>, dated Sun, 30 Oct 2005 21:21:45, seen in
news:comp.lang.javascript said:
function toDollars(amt)
{
if (0 == amt) return '0.00';
amt += ''; // Convert amt to string
amt = amt.split('.');
if (1 == amt.length) amt[1]='00';
if (0 == amt[1].length) amt[1] += '00';
if (1 == amt[1].length) amt[1] += '0';
return amt.join('.');
}

Or

function toDollars(amt) {
if (0 == amt) return '0.00'
amt = String(amt).split('.')
if (1 == amt.length) amt[1] = "0"
if (1 == amt[1].length) amt[1] += '0'
return amt.join('.') }

But that still requires, for \d+\.\d\d, String(amt) to show two decimal
places. Note : 0.06 + 0.01 -> 0.06999999999999999
 
R

Randy Webb

Dr John Stockton posted the following on 10/30/2005 2:10 PM:

<snip>

Why does your News Agent keep changing the Subject line, or, are you
doing that manually?
 
R

RobG

Dr said:
JRS: In article <4364ad27$0$20422$5a62ac22@per-qv1-newsreader-
01.iinet.net.au>, dated Sun, 30 Oct 2005 21:21:45, seen in
news:comp.lang.javascript said:
function toDollars(amt)
{
if (0 == amt) return '0.00';
amt += ''; // Convert amt to string
amt = amt.split('.');
if (1 == amt.length) amt[1]='00';
if (0 == amt[1].length) amt[1] += '00';
if (1 == amt[1].length) amt[1] += '0';
return amt.join('.');
}

Or

function toDollars(amt) {
if (0 == amt) return '0.00'
amt = String(amt).split('.')
if (1 == amt.length) amt[1] = "0"
if (1 == amt[1].length) amt[1] += '0'
return amt.join('.') }

But that still requires, for \d+\.\d\d, String(amt) to show two decimal
places. Note : 0.06 + 0.01 -> 0.06999999999999999

Yes, maybe expecting properly formatted strings in the first place was
unreasonable of me in the OP's case.

I suppose I was searching for a function that fulfills the requirement
of formating numbers for decimal currency with 2 places and that isn't
too daunting.

FAQ #4.6 has the heading "How do I convert a Number into a String with
exactly 2 decimal places?" but the advice provided seems out of place
with the heading.

The suggested solution seems much more appropriate to FAQ #4.7, I think
its complexity results in it either being put in the too-hard basket or
incorrectly applied (e.g. the OPs comments in this thread).

Perhaps FAQ #4.6 would be better if it provided a function that returns
exactly two decimal places.

The following should be suitable:

function twoDecimals(n)
{
var sign = (n<0)? '-':'';
n = Math.round(Math.abs(n)*100) + '';
while (n.length<3) n = '0'+n;
var len = n.length-2;
return sign + n.substring(0,len)+'.'+n.substring(len);
}

Noting that 'n' must be either an integer or floating point number.



While investigating the above, I noticed that Firefox has some
unexpected (buggy?) behaviour indicated below.

toFixed() is the native method and toFixedMod() is from FAQ#4.6:

var num = 2/0.3;

i (places) num.toFixed(i) num.toFixedMod(i)
13 6.6666666666667 6.6666666666667
14 6.66666666666667 6.66666666666667
15 6.666666666666667 6.666666666666668
16 6.6666666666666670 6.6666666666666670
17 6.66666666666666696 6.66666666666666800
18 6.666666666666666963 6.666666666666667000
19 6.6666666666666669627 6.6666666666666670000
20 6.66666666666666696273 6.66666666666666800000
21 6.666666666666666962726 6.666666666666667
22 6.6666666666666669627261 6.666666666666667
23 6.66666666666666696272614 6.666666666666667
24 6.666666666666666962726140 6.666666666666667

Interesting results for IE:
14 6.66666666666667 6.66666666666667
15 6.666666666666667 6.666666666666668
16 6.6666666666666670 6.6666666666666670
17 6.66666666666666700 6.66666666666666700
18 6.666666666666667000 6.666666666666667000
19 6.6666666666666670000 6.6666666666666670000
20 6.66666666666666700000 6.66666666666666700000
21 [object Error] 6.666666666666667
22 [object Error] 6.666666666666667
...

The modified toFixed suggested in the FAQ seems to provide limited
benefit to IE or Firefox, it may be better to offer it only for browsers
without a toFixed method and to suggest that floating point arithmetic
beyond 14(?) decimal places not be attempted with native JavaScript
functions.

I would think that anyone who was doing that and expecting accurate
results would thoroughly investigate all the issues anyway.


The test used to generate the above results is provided below.
Try..catch is used because IE fails silently with toFixed(i) if i>20 :

<script type="text/javascript">

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;
var 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 ? '-' : ''; }

function StrS(X, M, N) { return Sign(X)+StrU(Math.abs(X), M, N) }

Number.prototype.toFixedMod =
new Function('n','return StrS(this,1,n)')

</script>

<table border="1">
<tr><td colspan="3">
<script type="text/javascript">
var x = 2/0.3;
document.write(x);
</script>
</td>
</tr>
<tr>
<th>i (places)</th>
<th>num.toFixed(i)</th>
<th>num.toFixedMod(i)</th>
</tr>
<script type="text/javascript">

var tf, s='';
for (var i=10; i<25; ++i){

try {
tf = x.toFixed(i);
} catch (e) {tf = e;}

s += '<tr><td>' + i + '</td><td>'
+ tf + '</td><td>'
+ x.toFixedMod(i) + '</td></tr>';
}
document.write(s);
</script>

</table>
 
R

RobG

RobG wrote:
[...]
While investigating the above, I noticed that Firefox has some
unexpected (buggy?) behaviour indicated below.

Further testing in Safari 1.0.3 showed that is has no native toFixed
method and the FAQ's suggested routine fails beyond 8 decimal places:

i FAQ toFixed(i)
7 6.6666667
8 6.66666667
9 2.147483647
10 0.2147483647
11 0.02147483647
12 0.002147483647

Safari 1.3 showed results the same as Windows Firefox, as did the Mac
version of Firefox 1.0.7.

IE 5.2 (Mac) behaved the same as the Windows version, but again it has
no native toFixed method.

iCab (3.0 Beta) gives different results yet again, though it seems the
most consistent with the FAQ toFixed and shows a 14 place limit too:

i native toFixed FAQ toFixed
11 6.66666666667 6.66666666667
12 6.666666666667 6.666666666667
13 6.6666666666667 6.6666666666667
14 6.66666666666667 6.66666666666667
15 6.666666666666667 6.66666666666667
16 6.6666666666666670 6.66666666666667
17 6.66666666666666696 6.66666666666667
18 6.666666666666666963 6.66666666666667
19 6.6666666666666669627 6.66666666666667
20 6.66666666666666696273 6.66666666666667
21 RangeError 6.66666666666667
22 RangeError 6.66666666666667


And finally Opera 8.5 (Mac):

i native toFixed FAQ toFixed
14 6.66666666666667 6.66666666666667
15 6.666666666666667 6.666666666666668
16 6.6666666666666670 6.6666666666666670
17 6.66666666666666696 6.66666666666666800
18 6.666666666666666963 6.666666666666667000
19 6.6666666666666669627 6.6666666666666670000
20 6.66666666666666696273 6.66666666666666800000
21 [Error: name: RangeError ...] 6.666666666666667
22 [Error: name: RangeError ...] 6.666666666666667


It would seem that the toFixed suggested in the FAQ does not take
enough consideration of the shortcomings or vagaries of floating point
arithmetic in various browsers.

At least that should be noted, along with either a test harness to
determine the function's usefulness in various situations or a brief
description of what should be tested before using it.


[...]
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated
Sun, 30 Oct 2005 18:53:31, seen in Randy Webb
Dr John Stockton posted the following on 10/30/2005 2:10 PM:

<snip>

Why does your News Agent keep changing the Subject line, or, are you
doing that manually?

AIUI, it matches the Subject line, independently of case or spacing,
with the oldest possible known Subject line; and then uses that oldest
version, which may well be stored with spacing normalised, adding "Re: "
at the front if one is not already there. Or something like that.

It stores articles in an encrypted database, and, for speed of
searching, different parts may well be stored in different places.

Re: "Why?", for that you need to ask in where the originator and other experts are still to be found.

It may be concerned with threading-by-subject and the desire to ignore
inconsequential variations, and/or with a desire to protect against
"trap" Subjects such as
0.06+0.01!=0.07? vulgarity!

I presume that the practice was allowed by the RFCs extant at the time
of release, as the product is notorious for standards-compliance. The
authors may well have taken advantage of a possibility that few realised
was available.

You should see no change this time, AFAICS.
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Mon, 31
Oct 2005 07:35:42, seen in RobG
FAQ #4.6 has the heading "How do I convert a Number into a String with
exactly 2 decimal places?" but the advice provided seems out of place
with the heading.

The suggested solution seems much more appropriate to FAQ #4.7, I think
its complexity results in it either being put in the too-hard basket or
incorrectly applied (e.g. the OPs comments in this thread).

ISTM that the FAQ, if re-written, could have the Section numbers (1..5)
changed, do that the present Section 4 could be split and re-arranged
without confusion between, for example, the old and the new Section 4.8.
Then I'd put the present 4.6 before the present 4.5.

Perhaps FAQ #4.6 would be better if it provided a function that returns
exactly two decimal places.

The following should be suitable:

function twoDecimals(n)
{
var sign = (n<0)? '-':'';
n = Math.round(Math.abs(n)*100) + '';
while (n.length<3) n = '0'+n;
var len = n.length-2;
return sign + n.substring(0,len)+'.'+n.substring(len);
}

Noting that 'n' must be either an integer or floating point number.

A Number or numeric expression is expected (NaN & Infinity included),
but the version of StrU which I currently use is happy with a Boolean or
a Date Object, and passes an Array unchanged, and tolerates Strings,
Functions, and vars of value undefined.

Code in a recent article by Evertjan supports calculation in Cents with
output in Euros, and a (<G>my</G>) version should be included in a
<FAQENTRY> explicitly on why it's better to calculate in Cents.


While investigating the above, I noticed that Firefox has some
unexpected (buggy?) behaviour indicated below.

The modified toFixed suggested in the FAQ seems to provide limited
benefit to IE or Firefox, it may be better to offer it only for browsers
without a toFixed method

As in my js-round.htm and include1.js. But a Reliable Witness has said
that the toFixed supplied by MS is buggy. I'd recommend not using
toFixed at all; but, if you want something like it, implement say ToFixt
- the name is reminiscent of toFixed but does not imply the same bugs.

and to suggest that floating point arithmetic
beyond 14(?) decimal places not be attempted with native JavaScript
functions.

The number of decimal places should be irrelevant in general, though may
matter to toFixed and suchlike. The true limit is about 15 *significant
figures*.
 
D

Dr John Stockton

JRS: In article <4366154a$0$20411$5a62ac22@per-qv1-newsreader-
01.iinet.net.au>, dated Mon, 31 Oct 2005 22:59:54, seen in
news:comp.lang.javascript said:
RobG wrote:
[...]
While investigating the above, I noticed that Firefox has some
unexpected (buggy?) behaviour indicated below.

Further testing in Safari 1.0.3 showed that is has no native toFixed
method and the FAQ's suggested routine fails beyond 8 decimal places:

i FAQ toFixed(i)
7 6.6666667
8 6.66666667
9 2.147483647
10 0.2147483647
11 0.02147483647
12 0.002147483647

That needs investigating. It could be explained by Safari 1.0.3 using
IEEE Single or similar instead of IEEE Double.

Your best move, to discover more, might be to take the FAQ method, split
up the arithmetic statements so that each was as simple as possible, put
alerts between, and see where it goes wrong - or similar.

Test what 0.06+0.01 gives ; if it's not 0.06999999999999999 with 17
decimal places, worry about that instead.

Aha! 2147483647 + 1 is a well-known power of 2 : 2^31 in fact. Maybe
1.0.3 implements Math.round(X) as something like, but not matching, X|0.

You could replace
String(Math.round(X)) by String(X+0.5).replace(/\..*/, "")
to see what happens.

It would seem that the toFixed suggested in the FAQ does not take
enough consideration of the shortcomings or vagaries of floating point
arithmetic in various browsers.

Nothing beyond 14-15 digits is arithmetically meaningful, though ECMA
may define a specific result.


FAQ 4.6 is based on an older version of my code, for current see in my
js-round.htm; I think that page makes it clear enough that the methods
are intended to give correct meaningful results when used in a
meaningful manner, and will not necessarily agree to every digit with
toFixed or other code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top