JS wrote:

I've managed to create a simple script to convert between metric and

imperial. It works for CMS to INCHES and vice versa but not for KGS to

STONES/POUNDS. Can anyone shed any light on this?

Here's my code (CMS and INCHES which is working):

<input name="CM" type="text" VALUE="" size="3" maxlength="3"

onChange="eval('IN.value = ' + this.form.IN_expr.value)">

cms <em>or</em>

The correct abbreviation for centimetre is "cm" and the correct

abbreviation for kilograms is "kg".

<input name="IN" type="text" VALUE="" size="3" maxlength="3"

onChange="eval('CM.value = ' + this.form.CM_expr.value)">

inches<INPUT TYPE="hidden" NAME="CM_expr" VALUE="(Math.round(2.54 *

IN.value))">

<INPUT TYPE="hidden" NAME="IN_expr" VALUE="(Math.round(CM.value /

2.54))">

Almost any use of 'eval' is wrong or not required, see below.

Here's my code for KGS to STONES/POUNDS (not working):

[...] <INPUT TYPE="hidden" NAME="ST_expr" VALUE="(Math.round(KGM.value /

0.4536) / 14)"><INPUT TYPE="hidden" NAME="PNDS_expr"

VALUE="(Math.round(KGM.value / 0.4536) - ST.value)">

Firstly, I only want an integer in the result but am getting a decimal

to about 6 places.

That is because in the expression:

(Math.round(KGM.value / 0.4536) / 14)

Math.round applies to KGM.value/0.4536. You then divide by 14 to

create your decimal. Fixing syntax and guessing what you

intended:

Math.round((this.form.KGM.value/0.4536)/14)

Secondly, it appears that the + in (Math.round((ST.value * 14) +

PNDS.value) * 0.4536) is appending the PNDS.value to the ST.value * 14

so if PNDS.value is 0 and ST.value is 12 it calculates using 120.

Values from inputs are always treated as strings initially so

you must force them to become numbers if that is what is

required.

Your use of "ST.value * 14" forces ST.value to be a number, but

PNDS.value is a string, so it's concatenated, not added. To

force it to be a number add a '+' as follows:

...((this.form.ST.value*14 + +this.form.PNDS.value)*0.4536)

You can do other tricks too (multiply by 1, subtract instead of

add, etc.), but this way makes it obvious what you are doing.

Below is a different version that does away with 'eval' and the

hidden inputs, but beware that you don't do any validation of

input. There are also issues with the precision of JavaScript

mathematics, you should read here to get more information about

doing maths with javascript

:

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

<form action="">

<table>

<tr>

<td colspan="2">

All values rounded to nearest whole number

</td>

</tr><tr>

<td>

<input name="CM" type="text" VALUE="0" size="3"

maxlength="3" onChange="

// 1 inch = 2.54 cm

this.form.IN.value = Math.round(this.value/2.54);

"> cm <em>converts to</em>

</td><td>

<input name="IN" type="text" VALUE="0" size="3"

maxlength="3" onChange="

// 1 inch = 2.54 cm

this.form.CM.value = Math.round(this.value*2.54);

"> inches

</td>

</tr><tr>

<td>

<input name="KG" type="text" VALUE="0" size="3"

maxlength="3" onChange="

// 1 kg = 2.20462262 lbs

var x = Math.round(this.value*2.2046226);

// 14 lbs = 1 stone

this.form.ST.value = Math.floor(x/14);

this.form.LBS.value = x%14;

"> kg <em>converts to</em>

</td><td>

<input name="ST" type="text" VALUE="0" size="3"

maxlength="3" onChange="

this.form.KG.value = Math.round((this.value*14

+ +this.form.LBS.value)/2.2046226);

">St

<input name="LBS" type="text" VALUE="0" size="3"

maxlength="3" onChange="

this.form.KG.value = Math.round((this.form.ST.value*14

+ +this.value)/2.2046226);

">lbs</p>

</td>

</tr><tr>

<td colspan="2">

<input type="reset" onclick="if(this.blur) this.blur();">

</td>

</tr>

</table>

</form>

--

Rob