scrip drops a penny when amount ends with .d0

E

eyoung

I call a function that takes the unit price and quantity ordered to
create an amount...it looks something like this.

function calculateCost()
{
quantity=document.RFO.quantity.value;
unitPrice=document.RFO.unitPrice.value;
total=0;
if(isPositiveInteger(quantity))
{
quantity=parseFloat(quantity)
{
total=quantity * unitPrice;
}
}
document.RFO.total.value=format(total)
}

if a person enters a unit price that ends with .10, .20, .30, ..., .90,
my code drops a penny off the total? However if the price ends with .1,
..2, .3, ..., .9, my code works fine.
Seems it has a problem calculating prices ending with 0 unless it's .00
 
D

Dr John Stockton

JRS: In article <[email protected]>
, dated Tue, 9 May 2006 08:32:06 remote, seen in
I call a function that takes the unit price and quantity ordered to
create an amount...it looks something like this.

function calculateCost()
{
quantity=document.RFO.quantity.value;
unitPrice=document.RFO.unitPrice.value;
total=0;
if(isPositiveInteger(quantity))
{
quantity=parseFloat(quantity)
{
total=quantity * unitPrice;
}
}
document.RFO.total.value=format(total)
}

if a person enters a unit price that ends with .10, .20, .30, ..., .90,
my code drops a penny off the total? However if the price ends with .1,
.2, .3, ..., .9, my code works fine.
Seems it has a problem calculating prices ending with 0 unless it's .00



Your code lacks isPositiveInteger and format, so cannot be tested by me.

Your first move should be to omit use of format, since you need to know
whether there is an error up to that stage; or to try alert(total)
before that. H'mmm - I notice you use total in two ways - that is
at best injudicious; change one of them, to be safe.

It seems illogical to use parseFloat on something just shown to be
integer; you could use unary + instead; you don't need that line, unless
you must allow trailing characters.

Get a proper newsreader, with spelling-checker; Google is a bad
interface; read newsgroup FAQ 2.3, 4.6, 4.7 before posting a reply.
 
R

Richard Cornford

I call a function that takes the unit price and
quantity ordered to create an amount...it looks
something like this.

function calculateCost()
{
quantity=document.RFO.quantity.value;
unitPrice=document.RFO.unitPrice.value;
total=0;

The variables - quantity -, - unitPrice - and - total - should be
declared local to the function using the - var - keyword whenever there
is no good reason for them being global (and there doesn't appear to be
any reason for that).
if(isPositiveInteger(quantity))
{
quantity=parseFloat(quantity)

Why - parseFloat -? Surly a quantity has got to be an integer (and
particularly if - isPositiveInteger - does what its name suggests), so
why not - parseInt - and if you are verifying that the string contains a
representation of a positive integer why not let the type conversion
implicit in multiplication do that job.
{ ^
total=quantity * unitPrice;
}
^

What are these opening and closing braces doing here? They form a Block
statement, but there is no reason for a Block statement appearing here.
}
document.RFO.total.value=format(total)
}

if a person enters a unit price that ends with .10,
.20, .30, ..., .90, my code drops a penny off the
total? However if the price ends with .1, .2, .3,
..., .9, my code works fine. Seems it has a problem
calculating prices ending with 0 unless it's
.00

There is nothing in this code that would suggest the phenomenon you
describe. A quick test of the javascript operations you are using finds
no evidence of differing results using strings with trailing zeros and
the same strings with the trailing zeros stripped off:-

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
</head>
<body>
<pre>
<script type="text/javascript">

var l = [
'1.00','1.10','1.20','1.30','1.40','1.50','1.60','1.70','1.80','1.90',
'2.00','2.10','2.20','2.30','2.40','2.50','2.60','2.70','2.80','2.90',
'3.00','3.10','3.20','3.30','3.40','3.50','3.60','3.70','3.80','3.90',
'4.00','4.10','4.20','4.30','4.40','4.50','4.60','4.70','4.80','4.90',
'5.00','5.10','5.20','5.30','5.40','5.50','5.60','5.70','5.80','5.90',
'6.00','6.10','6.20','6.30','6.40','6.50','6.60','6.70','6.80','6.90',
'7.00','7.10','7.20','7.30','7.40','7.50','7.60','7.70','7.80','7.90',
'8.00','8.10','8.20','8.30','8.40','8.50','8.60','8.70','8.80','8.90',
'9.00','9.10','9.20','9.30','9.40','9.50','9.60','9.70','9.80','9.90'
];
var q = [
'1','2','3','4','5','6','7','8','9'
];

function isPositiveInteger(){
return true;
}

function calculateCost2(x, y){
quantity = q[y];
unitPrice = l[x];
total=0;
var unitPrice2, total2;
if(isPositiveInteger(quantity)){
quantity = parseFloat(quantity)
{
total = quantity * unitPrice;
unitPrice2 = unitPrice.substring(0, (unitPrice.length - 1));
total2 = quantity * unitPrice2;
}
}
return (quantity+' * '+unitPrice+' = '+total+'\n'+quantity+' * '+
unitPrice2+' = '+total2+'\t\t'+
((total != total2)?'********** Differ **********':''));
}

for(var c = 0;c < q.length;++c){
for(var d = 0;d < l.length;++d){
document.write(calculateCost2(d, c)+'\n\n')
}
}

</script>
</per>
</body>
</html>

With no evidence of the phenomena it cannot be attributed. You will have
to create an example that actually shows this in action. It would be a
good idea to mention the browser you are using in case this is an
implementation specific bug (I used IE and Mozilla for testing the above
code).

(Incidentally, although the FAQ reference VK posted is relevant to the
issues of money calculations and number to formatted string
transformations, it cannot account for the symptoms you describe. VK
should generally be ignored, he does not know javascript at all and as a
result he cannot see what would be expected from executing javascript
code, and so is incapable of attributing effects to causes except by
(inevitably often wrong) guess-work.)

Richard.
 
E

eyoung

I wrote a basic code because the real code has so much other stuff
going on. My code allows the user to add as many lines of items to be
purchased...so I have no idea how many items to total up for line item
or main total, so this statement gets all the sets of values.
The problem is only seen when 3 or 6 items are purchased at a cost of
..70 cents...that's the only time it's wrong.
My code gives the following totals
3 * .70 = 2.09
6 * .70 = 4.19

btw, I'm not asking for anyone's thoughts using eval...I had no choice
but to use it, the information is coming from some visual basic
statements and would not work without the eval...I also had to use the
Visual Basic to create collapsible / expandable items to be purchased
area.

My code:
for(i=2;i<=nrow;i++) {
eval("quant" + i + "=document.RFO.quant_" + i + ".value");
eval("unit" + i + "=document.RFO.unit_" + i + ".value");
eval("tot" + i + "=0");

eval("tquant=quant" + i + "");
eval("tunit=unit" + i + "");
eval("ttot=tot" + i + "");

if(isPositiveInteger(tquant))
{
tquant=parseFloat(tquant)
{
ttot=tquant * tunit;
}
}
eval("document.RFO.tot_" + i + ".value=format(ttot)");
}


For testing, I have stripped to code down to nothing which only ran on
the first set of values...the code I listed before...and I get the same
results. I then changed it a bit after reading your statments
here...even removing the isPositiveInteger statment to make sure the
problem was not there. I still get the same result, every combination
of values work except 3 or 6 items at a price of ".70" or ".7"

function calculateCost()
{
nrow=document.RFO.nrow.value;
quant1=document.RFO.quant_1.value;
unit1=document.RFO.unit_1.value;
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
}
document.RFO.tot_1.value=format(tot1)
 
L

Lee

(e-mail address removed) said:


if(isPositiveInteger(tquant))
{
document.RFO.elements["tot_"+i].value=tquant*tunit;
}

You haven't shown us your format() function. As suggested
before, run without it to determine if it's the problem.


--
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Tue, 9
May 2006 22:29:06 remote, seen in Richard
Cornford said:
(Incidentally, although the FAQ reference VK posted is relevant to the
issues of money calculations and number to formatted string
transformations, it cannot account for the symptoms you describe. VK
should generally be ignored, he does not know javascript at all and as a
result he cannot see what would be expected from executing javascript
code, and so is incapable of attributing effects to causes except by
(inevitably often wrong) guess-work.)

<FAQENTRY>

FAQ 4.6 should, to allow for the limitations of new arrivals, cite FAQ
4.7. 4.7 indicates why rounding (rather than truncation) is needed even
for calculations nominally exact in pennies.

Append ' <i>ff.</i>' to the line containing the first URL.

2.6 para 2 sentence 2 word 11 seems too short (in my WWW copy). The
error was introduced in version 8.0.

</FAQENTRY>


Anyone citing the FAQ to a Googler should generally cite also FAQ 2.3;
paragraph numbering within 2.3 would be helpful (just do it manually in
the source).
 
E

eyoung

if(isPositiveInteger(tquant))
{
document.RFO.elements["tot_"+i].value=tquant*tunit;
}

You haven't shown us your format() function. As suggested
before, run without it to determine if it's the problem.

keep reading...I removed the function as well as other stuff to test
the code.
 
R

Richard Cornford

I wrote a basic code because the real code has so much other stuff
going on. My code allows the user to add as many lines of items to be
purchased...so I have no idea how many items to total up for line item
or main total, so this statement gets all the sets of values.
The problem is only seen when 3 or 6 items are purchased at a cost of
.70 cents...that's the only time it's wrong.
My code gives the following totals
3 * .70 = 2.09
6 * .70 = 4.19
function calculateCost()
{
nrow=document.RFO.nrow.value;
quant1=document.RFO.quant_1.value;
unit1=document.RFO.unit_1.value;
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
}
document.RFO.tot_1.value=format(tot1)

Once again the output from this function should not be expected to
produce differing results for input of quantity '3' or '6' and unit
price '.7' and '.70', and it does not:-

function cCost() {
quant1= '3';
unit1= '.7';
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
return tot1;
}
function cCost2() {
quant1= '3';
unit1= '.70';
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
return tot1;
}

alert(cCost()+'\n'+cCost2());
/*
alerts:-
2.0999999999999996
2.0999999999999996
*/

With input values both '.7' and .07' the output is the same number.

You will not be able to attribute the problem unless you post some code
that demonstrates it.

Richard.
 
E

eyoung

I used the same code you used above...and got the same conclusiong.
3 * .7 = 2.0999999999999996
6 * .7 = 4.199999999999999
WRONG ANSWERS

A correct response should be:
3 * .7 = 2.10
6 * .7 = 4.20

The above code gives the correct resonse to all other calculations that
I have tried.
 
L

Lasse Reichstein Nielsen

btw, I'm not asking for anyone's thoughts using eval...

You don't have to ask :)
I had no choice but to use it,

"I have been driven many times upon my knees by the overwhelming
conviction that I had nowhere else to go." - Abraham Lincoln
eval("quant" + i + "=document.RFO.quant_" + i + ".value");

Try:
window["quant"+i] = document.RFO["quant_"+i].value;
or more standards compliant:
window["quant"+i] = document.forms['RFO'].elements['quant_'+i].value;

We don't want to give people the idea that they have to use eval
for property access.

/L
 
E

eyoung

The Question again.....

function cCost() {
quant1= '3';
unit1= '.7';
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
return tot1;
}
function cCost2() {
quant1= '6';
unit1= '.70';
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
return tot1;
}


alert(cCost()+'\n'+cCost2());
/*
alerts:-
2.0999999999999996
4.199999999999999
*/


3 * .7 = 2.0999999999999996
6 * .7 = 4.199999999999999
WRONG ANSWERS

Use your calculators
A correct response should be:
3 * .7 = 2.10
6 * .7 = 4.20


The above code gives the correct resonse to all other calculations that

I have tried.
 
L

Lee

(e-mail address removed) said:
The Question again.....

function cCost() {
quant1= '3';
unit1= '.7';
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
return tot1;
}
function cCost2() {
quant1= '6';
unit1= '.70';
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)
{
tot1=quant1 * unit1;
}
return tot1;
}


alert(cCost()+'\n'+cCost2());
/*
alerts:-
2.0999999999999996
4.199999999999999
*/


3 * .7 = 2.0999999999999996
6 * .7 = 4.199999999999999
WRONG ANSWERS

Those answers are as close to correct as you can expect.
See if you can calculate the percentage of error.
Then convert them to strings and round them off, if you
want them to look pretty.


--
 
R

Richard Cornford

I used the same code you used above...and got the same
conclusiong.
3 * .7 = 2.0999999999999996
6 * .7 = 4.199999999999999
WRONG ANSWERS

How can they be the wrong answers? They are the numbers generated by the
operations used in _your_ - calculateCost - function when given the
parameters you specified, and they are the numbers expected given that
the calculations are performed with IEEE double precision floating point
arithmetic and baring in mind that that number format is not capable of
representing all numeric values precisely (as no number format is).

I posted those functions to demonstrate that the issue you stated; that
you got differing results depending on whether the input was '.7' or
'.70', was not manifest in the code you posted. The training zero digit
on the input does not alter the numbers generated by the operations
used.
A correct response should be:
3 * .7 = 2.10
6 * .7 = 4.20

Neither of those numbers can be represented by an IEEE double precision
floating point number (in just the same way as a decimal format cannot
precisely represent 1/3).

If you mean that you want the formatted _string_ output to be '2.10' and
'4.20' from the numbers 2.0999999999999996 and 4.199999999999999
respectively then you need a (decent) number to string formatting
function. Or the one you have (the one you have been repeatedly asked to
post) is not suited to its task.
The above code gives the correct resonse to all other
calculations that I have tried.

There is no code in your post, 'above' or otherwise.

Richard.
 
L

Lasse Reichstein Nielsen

The Question again.....

What question? I see no question here.
function cCost() {
quant1= '3';
unit1= '.7';
tot1=0;
quant1=parseInt(quant1)
unit1=parseFloat(unit1)

It is sufficient, and equivalent, to write;
quant1 = 3;
unit1 = 0.7;
Parsing from a string gives the same value as parsing the
literal.

3 * .7 = 2.0999999999999996
6 * .7 = 4.199999999999999
WRONG ANSWERS

Wrong question.

You write ".7" and have it parsed to a double precission floating
point number (the only number type in Javascript).
Since 7/10 is not exactly representable as a double, the value of
the literal becomes the closest representable value, which is
sligtly less than 7/10. Let's call it 7/10-epsilon.

You then multiply this value by 3 (which can be represented exactly)
and the result is 21/10-3*epsilon.

Multipliciation increases the error. For laughs, try displaying;
2.1-3*0.7

You then try to convert this value back to a string displaying a
decimal representation of the number. That is the value you see.
it's far enough from 2.1 to not be show as that.
The above code gives the correct resonse to all other calculations that
I have tried.

Try some more. It's a general problem. Do not use fractional numbers
if you need exact results.

I believe using floating point numbers for monetary calculations is
even illegal in some cases (without knowing which :).

/L
 
D

Dr John Stockton

JRS: In article <[email protected]>
, dated Wed, 10 May 2006 07:59:33 remote, seen in
news:comp.lang.javascript, (e-mail address removed) posted :

You were asked to read the FAQ before posting a reply. If you had done
so, you should have learned how to format newsgroup replies. Read
section 2.3 now.

I wrote a basic code because the real code has so much other stuff
going on. My code allows the user to add as many lines of items to be
purchased...so I have no idea how many items to total up for line item
or main total, so this statement gets all the sets of values.
The problem is only seen when 3 or 6 items are purchased at a cost of
.70 cents...that's the only time it's wrong.
My code gives the following totals
3 * .70 = 2.09
6 * .70 = 4.19

This document.writeln(3*.70, ", ", 6*.70)
gives 2.0999999999999996, 4.199999999999999
Read FAQ 4.7, and my site, to see why.

Evidently, your format function truncates. You should have posted
it or replaced it with a known-good, tested one.

Read FAQ 4.6, and my site, on rounding from Number to String.

btw, I'm not asking for anyone's thoughts using eval...

You get what you need, which is not necessarily what you want.
I had no choice
but to use it, the information is coming from some visual basic
statements and would not work without the eval...

It's rarely necessary to use eval; it appears to be so to you because
you are inadequately informed. Read FAQ 4.40, 4.39, and cited notes.
I also had to use the
Visual Basic to create collapsible / expandable items to be purchased
area.

That you used it is credible, but that you needed to is not.

But thank you for so amply illustrating a point that I made recently.
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top