Newbie error in calculation script

P

Phil Sowden

I am a newbie with a VBscript background, trying to get my head round
the isNaN function! All I want to do is add two numbers on a page.

My procedure was fine before I added the "validation" code in the
"setnum" function below. It previously worked with the parseFloat
function rather than setnum, but of course, only if I entered
numerics. I just want to total the fields on my form, ignoring
non-numeric values (treating them as zero).

Also, do I need to round the figures to get the total with 2 d.p.?

Can anybody help me with the code below? I just get Error on page,
irrespective of what values I use.

TIA

Phil


function setnum(fldid) {
if ( isNaN(parseFloat(fldid)) {
return 0
}
else {
return parseFloat(fldid)
}
}

function CalcTotal() {
document.forms[0].txtTotalCost.value =
setnum(document.forms[0].txtInvAmount.value) +
setnum(document.forms[0].txtCourier.value);
}
 
F

Fred Oz

Phil Sowden wrote:
[snip]
Can anybody help me with the code below? I just get Error on page,
irrespective of what values I use. [snip]

function setnum(fldid) {
if ( isNaN(parseFloat(fldid)) {
return 0
[snip]

Try replacing the above with:

function setnum(fldid) {
var a = parseFloat(fldid);
if (isNaN(a)) {
return 0;


Of course, you still have lots of work to do to validate the input.
parseFloat keeps grabbing characters until it doesn't get any more
numbers, so "16.7abc" will be returned as "16.7". So what your
function does is make a half-hearted attempt to make a number from
whatever is entered. Also, you are only testing for numbers - do you
want dollars and cents? Fractions? How many significant digits?

If I enter:

txtInvAmount: 1/5
txtCourier: 2.5

your function returns:

txtTotalCost: 3.5

You function also explicitly returns zero (0) if text is entered
(though if the first characters are digits, parseFloat will return them
as noted above).

You need to format txtTotalCost to give $0.00 (I think) too, and you
should disable the field so users can't simply put whatever they like
in there. Even better, write it to the document itself so users are
not tempted to modify it.

Anyhow, enough beating around the head! Here is what you need to do:

1. Test that only digits and one decimal point have been entered. If
not, give an alert and ask the user to fix it.

2. If the above test is passed, make sure a max of two decimal places
have been used.

3. If 2. is passed, format whatever they have typed in so it has two
places (5.2 becomes 5.20) and tidy the field.

3. Test that the numbers are reasonable - you should have some idea what
that should be.

4. Do the maths and write your formatted answer to the total.

Here is the text of a couple of posts from a few weeks ago - between the
two you should get the idea.


This one just tests if a number is an int or float:

Testing strings using regular expressions to see if they have
decimal places (and how many), surplus characters, scientific
notation, etc. requires exhaustive testing... let JS do
the work.

How about:

var x = someValue;
if (x == parseInt(x) && x == parseFloat(x)) {
alert(x + ' is a int');
} else if (x == parseFloat(x)) {
alert(x + ' is a float');
} else {
alert(x + ' is not a number I like...');
}

You can even use scientific notation if you like, so 1.2e+03 is
recognised as a float quite happily without complex pattern
matching.


Here is the followup from Mike Winter that shows how to use regular
expresions to test number input:
Testing strings using regular expressions to see if they have
decimal places (and how many), surplus characters, scientific
notation, etc. requires exhaustive testing [...]


Not at all:

/^(0|[1-9])\d*$/

ensures that the string contains an integer with no leading zeros.

/^(-|+)?(0|[1-9])\d*$/

allows for signed integers.

To check for basic real numbers, it can be modified to:

/^(0|[1-9])\d*(\.\d+)?$/

which allows integer or real number inputs. To force decimal places and
to limit their number again, only simple modification is necessary:

/^(0|[1-9])\d*\.\d+$/ // must be real
/^(0|[1-9])\d*\.\d\d$/ // must be real with two decimal places
/^(0|[1-9])\d*\.\d{1,5}$/ // must be real with at most five d.p.

Scientific notation:

/^(0|[1-9])\d*\.\d+e(-|+)?\d+$/i

Optional scientific notation:

/^(0|[1-9])\d*\.\d+(e(-|+)?\d+)?$/i

Optional scientific notation with positive and negative numbers:

/^(-|+)?(0|[1-9])\d*\.\d+(e(-|+)?\d+)?$/i

Mandatory canonical scientific notation:

/^(-|+)?[1-9]\.\d+e(-|+)?[1-9]\d*$/i

Hexadecimal:

/^0x[0-9a-f]+$/i

[Note: these are untested]

The problem with using parseInt and parseFloat is that parsing stops at
an unrecognised character. That doesn't really tell you if the value's
format is correct or not, just that part of it converts to a number. If
you want check an input format, regular expressions are the best approach.

As you can see from the above, it doesn't take much effort once you've
established some basic patterns. After that point, it's simply a matter
of adding the components in the appropriate places.
How about:

var x = someValue;
if (x == parseInt(x) && x == parseFloat(x)) {


Calling parseInt without a radix argument can be unpredictable. Don't do
it.

[snip]

Mike
 
P

Phil

Mike,

I think that's probably just enough information for me to fix it!!!!

Thanks ever so much, I return to the task invigorated and educated.
I'll put a bit more formatting / validation code in there, too.

Phil
 
P

Phil

First of all, apologies, Fred - I did realise I'd posted my appreciation
to "Mike" just after I hit the magic button. As you see, "Mike" was the
last word on the posting, so I got that wrong.

Anyway, I managed to get my unformatted fields to work exactly as
intended, thanks to your assistance. I'll be fiddling with the
formatting overnight tonight, I bet. In the meantime, it's a GIGO
system, but it works!

Thanks again - to both of you! :)

Phil
 
D

Dr John Stockton

JRS: In article <[email protected]>,
dated Tue, 12 Oct 2004 01:48:50, seen in Phil
Sowden said:
I just want to total the fields on my form, ignoring
non-numeric values (treating them as zero).

That's probably a mistake, though not necessarily yours.

Consider : in a column of UK prices such as £1.23, NIL may reasonably be
taken for zero, $1,23 may be two typing errors, 1e3 is questionable, -
3.45 is improbable, etc. It is not for the programmer to make
questionable assumptions about flawed data; get the data entry person to
put it right, if the numbers do not match the appropriate format. For
example, you might allow 2 and 2.00 as meaning two pounds, but 2.0
should not be allowed.
Also, do I need to round the figures to get the total with 2 d.p.?

Before posting, you should have read the newsgroup FAQ; Sections 4.7 &
4.6 are relevant to that point.

Also, if all entries are multiples of 25p, rounding will not be needed.

Possibly unless you work for Mr Brown, you can avoid such worries
(generally) by working in exact pence rather than approximate pounds.
 
J

Jc

You've got the right idea, looks like you're just missing an ending
parentheses (first line of your setnum function).
 
M

Michael Winter

[Quoting me]
/^(0|[1-9])\d*$/

This should have actually been

/^(0|[1-9]\d*)$/

Where this same pattern, (0|[1-9])\d*, occurs in other expressions (almost
all), it should be replaced with (0|[1-9]\d*).

[snip]

Mike
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top