problem with javascript in asp not rounding up..

G

GTN170777

Hi All,

I have a neat little script that calculates price based on quantity without
refreshing the page.. the script is -

<script type="text/javascript">
function OpenWin(url)
{
window.open(url,'win','scrollbars=1,status=0,resizable=0,width=200,height=265');
}


function btnCalculate_onclick()
{
var numQty;
var adprice;

if (isNaN(document.frmClient.txtQty.value))
{
alert('Please enter a number for advert quantity.');
}
else
{
numQty = parseInt(document.frmClient.txtQty.value);
adprice = parseInt(document.frmClient.adprice.value);

if((numQty >= 1) && (numQty <= 1)){
document.getElementById('divPrice').innerHTML = '£' + adprice + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(100*(adprice * numQty))/100 + ' + VAT';
} else if((numQty >= 2) && (numQty <= 10)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.95)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.95 + ' + VAT';
} else if((numQty >= 11) && (numQty <= 20)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.85)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.85 + ' + VAT';
} else if((numQty >= 21) && (numQty <= 30)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.75)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.75 + ' + VAT';
} else if((numQty >= 31) && (numQty <= 50)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.5)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.5 + ' + VAT';
} else {
alert("Please contact us for more information about the benefits of our
monthly account packages.");
}
}
}</script>

The problem I have is that it doesn't round up, for instance in stead of
£0.95 i get £0.9499999999998.

Does anyone have any ideas how to fix this?

Many thanks
 
A

Adrienne Boswell

Gazing into my crystal ball I observed =?Utf-8?B?R1ROMTcwNzc3?=
<[email protected]> writing in

ASP has no knowledge of the client, this is a client side issue.
Followups set to comp.lang.javascript.
 
A

Anthony Jones

GTN170777 said:
Hi All,

I have a neat little script that calculates price based on quantity without
refreshing the page.. the script is -

<script type="text/javascript">
function OpenWin(url)
{
window.open(url,'win','scrollbars=1,status=0,resizable=0,width=200,height=26
5');
}


function btnCalculate_onclick()
{
var numQty;
var adprice;

if (isNaN(document.frmClient.txtQty.value))
{
alert('Please enter a number for advert quantity.');
}
else
{
numQty = parseInt(document.frmClient.txtQty.value);
adprice = parseInt(document.frmClient.adprice.value);

if((numQty >= 1) && (numQty <= 1)){
document.getElementById('divPrice').innerHTML = '£' + adprice + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(100*(adprice * numQty))/100 + ' + VAT';
} else if((numQty >= 2) && (numQty <= 10)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.95)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.95 + ' + VAT';
} else if((numQty >= 11) && (numQty <= 20)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.85)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.85 + ' + VAT';
} else if((numQty >= 21) && (numQty <= 30)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.75)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.75 + ' + VAT';
} else if((numQty >= 31) && (numQty <= 50)){
document.getElementById('divPrice').innerHTML = '£' +
(Math.round(adprice * numQty)*.5)/numQty + ' + VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
Math.round(adprice * numQty)*.5 + ' + VAT';
} else {
alert("Please contact us for more information about the benefits of our
monthly account packages.");
}
}
}</script>

The problem I have is that it doesn't round up, for instance in stead of
£0.95 i get £0.9499999999998.

Does anyone have any ideas how to fix this?

The short answer is do not concatenate a number directly in to a string use
the Number object's .toFixed method.

var n = 250 * 0.83
var s = n.toFixed(2)

However while I'm here have you noticed that the code in each of your Ifs
are identical except for that multiplier value changes? This pattern should
cause you to see a need for a function the can get the multiplier value. In
the code below I've refactored out a function which returns the discount for
a specified quantity. Note that by returning the actual discount in this
function it makes the relationship between the quantity and the discount
given much clearer.


I've made a business decision (which clearly you may disagree with) to
discount the unit price then multiply the quantity by the discounted price.
This is less likely to be disputed by a user IMO.

I use Math.round to ensure the discounted price is to the nearest penny.
That still doesn't eliminate the need to use .toFixed since Numbers are
stored as floating point values which cannot exactly represent numbers
exactly only to a reasonable degree of precision.


function btnCalculate_onclick()
{

var numQty = parseInt(document.frmClient.txtQty.value);
var adprice = parseInt(document.frmClient.adprice.value);

if (isNaN(numQty))
{
alert('Please enter a number for advert quantity.');
}
else
{
var multiplier = null;

try { multiplier = 1 - getDiscount(numQty) }
catch(e) { alert(e); }

if (multiplier)
{
var discountedUnitPrice = Math.round(adprice * multiplier * 100) / 100
document.getElementById('divPrice').innerHTML = '£' +
discountedUnitPrice.toFixed(2) + '+ VAT';
document.getElementById('maindivPrice').innerHTML = '£' +
(discountedUnitPrice * numQty).toFixed(2) + ' + VAT';
}
}
}

function getDiscount(numQty)
{
if (numQty <= 1) return 0
if (numQty <= 10) return 0.05
if (numQty <= 20) return 0.15
if (numQty <= 30) return 0.25
if (numQty <= 50) return 0.5
throw "Please contact us for more information about the benefits of our
monthly account packages."
}
 
A

Anthony Jones

Dave Anderson said:
There are boundless examples. My grandparents managed to avoid it their
entire lives.


Great you've got plenty to choose from then, perhaps you could just present
just one?
 
D

Dave Anderson

Anthony said:
Great you've got plenty to choose from then, perhaps you could just
present just one?

MAN1: It hurts when I hit my fingers with a hammer.
MAN2: Try to avoid hitting your fingers.
MAN3: How could MAN1 do that?
MAN2: By not hitting them with a hammer.
MAN3: Can you give me examples? Just one?

Do you really want to go down this path, Anthony?
 
D

Dave Anderson

Anthony said:
...Numbers are stored as floating point values which cannot
exactly represent numbers exactly only to a reasonable degree
of precision...

This is not completely true. IEEE 754 double-precision floating point
numbers CAN and DO represent integers between -9007199254740992 and
9007199254740992 exactly. In addition, there are a whole bunch of
non-integer rational numbers that can be precisely represented.

Since you like examples, here's one:

EXAMPLE: 0.5
 
A

Anthony Jones

Dave Anderson said:
MAN1: It hurts when I hit my fingers with a hammer.
MAN2: Try to avoid hitting your fingers.
MAN3: How could MAN1 do that?
MAN2: By not hitting them with a hammer.
MAN3: Can you give me examples? Just one?

Do you really want to go down this path, Anthony?


Yes, yes! Show me please a simple example of avoiding using binary digits
to represent a non-integer rational number?
 
A

Anthony Jones

Dave Anderson said:
This is not completely true. IEEE 754 double-precision floating point
numbers CAN and DO represent integers between -9007199254740992 and
9007199254740992 exactly. In addition, there are a whole bunch of
non-integer rational numbers that can be precisely represented.

By 'numbers' I meant the whole set of numbers. Not just a finite few.

Since you like examples, here's one:

EXAMPLE: 0.5

I get the idea poor, choice of example though. 0.5 is a power of 2
therefore a mantissa with the value of 2 and an exponent of -1 exactly
represents 0.5. Mind you it was 20 years ago that I read the 754 spec I
could be wrong ;)
 
D

Dave Anderson

Anthony said:
Yes, yes! Show me please a simple example of avoiding using
binary digits to represent a non-integer rational number?

Since I cannot easily avoid representing text while posting to USENET, I
will not try. But I will offer a description of a real-world example:

<written on chalkboard> 7/3 </written on chalkboard>

You forgot to ask for EXACT representation, BTW.
 
D

Dave Anderson

Anthony said:
By 'numbers' I meant the whole set of numbers. Not just a finite few.

There is no way to represent every member of ANY infinite set with a finite
set of bits, so what else could you mean? Let's at least agree on this --
ECMA/J/JavaScript Number Objects can not represent more than 2^64 unique
values.

I get the idea poor, choice of example though. 0.5 is a power of 2
therefore a mantissa with the value of 2 and an exponent of -1 exactly
represents 0.5.

Doesn't that actually make it an *illustrative* choice of example, since the
only non-integer rationals that can be precisely represented with IEEE 754
floats MUST have only powers of two in the denominator?
 
A

Anthony Jones

Dave Anderson said:
Since I cannot easily avoid representing text while posting to USENET, I
will not try. But I will offer a description of a real-world example:

<written on chalkboard> 7/3 </written on chalkboard>

You forgot to ask for EXACT representation, BTW.


Oh I see now what you meant was to stop asking a computer to represent
non-integer rational number.

That little funny probably worked with the brain-boxes who got via the
Maths/Physics degrees. Some of us got here the hard way. I didn't get it.
I thought you actually being serious and I was missing something
fundemental.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]

You could try reading the FAQ of comp.lang.javascript, and/or my site.

A programmer should know that binary floats can represent few simple
decimal fractions exactly.

If your results are hoped to be in pounds, with a 2-digit decimal
fraction part, then calculate in pence and insert the point as part of
output formatting.
 
A

Anthony Jones

Dr J R Stockton said:
In comp.lang.javascript message <[email protected]


You could try reading the FAQ of comp.lang.javascript, and/or my site.

A programmer should know that binary floats can represent few simple
decimal fractions exactly.

If your results are hoped to be in pounds, with a 2-digit decimal
fraction part, then calculate in pence and insert the point as part of
output formatting.


The floating point type works sufficiently for most reasonable figures such
as in this case. It has to be understood that you need to be careful when
dealing with money since from a users perspective you can present inaccurate
figures due to rounding problems even when using integer math internally.

In the abscence of a decimal type, unless you demonstrate really good
reasons otherwise, stick with float and keep it simple. Dealing with
figures in the the £10K region with simple percentage calculations will not
result in bad stuff happening. Especially if the customer likes to see how
things are calculated and the figures they see on screen need to add up.
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top