# Convert Units Of Distance (Miles, Meters, Kilometer), Rounding Issues

Not sure if it is the conversion formulas, rounding formula or just logic. But on the sample below, select "marathon" and I am using 42195 meters as seen in the html code.  This gets converted to kilometers 42.197 which seems odd.  then use then use the drop down to change from kilometers, to miles, to meters and back to kilometers and the number is not the same in the text box. It is now 42.199

http://jsbin.com/codowocore/edit?html,js,output
JQUERY
``````\$(function() {

// select length of run
var currentMeasure = \$('select#distanceUnit option:selected').text(); // current distance unit (miles, meters)
\$('#distanceSelect').on('change', function() { // get the distance from drop down
var distanceSelect = \$('#distanceSelect').val();
var convertTo = \$('select#distanceUnit option:selected').text(); // convert from meters or what is currently selected to new measure
if (distanceSelect !== '') {
// convert distance to selected distance unit
var c = convert('Meter', convertTo, distanceSelect);
// place converted lenght in text box
\$('#distance').val(c);
}

});

// recalculate the distance measure if change unit of measure
\$('#distanceUnit').on('change', function() {

var currentDistance = \$('#distance').val();
var newMeasure = \$(this).val();

var newDistance = convert(currentMeasure, newMeasure, currentDistance);

\$('#distance').val(newDistance);
currentMeasure = newMeasure;

});

});

function convert(from, to, dist) {

var conv;
switch (from + to) {

// convert from meters
case 'MeterKilometer':
conv = dist * 0.001;
break;
case 'MeterMile':
conv = dist * 0.00062137119223733;
break;
case 'MeterMeter':
conv = dist * 1;
break;

// convert from miles
case 'MileKilometer':
conv = dist * 1.609344;
break;
case 'MileMile':
conv = dist * 1;
break;
case 'MileMeter':
conv = dist * 1609.344;
break;

// convert from kilometer
case 'KilometerKilometer':
conv = dist * 1;
break;

case 'KilometerMile':
conv = dist * 0.62137119223733;
break;
case 'KilometerMeter':
conv = dist * 1000;
break;

}
convr = Math.ceil(conv*1000)/1000;
return convr;
}
``````

HTML
``````<!DOCTYPE html>
<html>
<script src="https://code.jquery.com/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
<body>
<form>

<div class="form-group">
<label>Distance</label>
<select id="distanceSelect" name="distanceSelect">
<option value="">Custom</option>
<option value="42195">Marathon</option>
<option value="21097.5">Half-Marathon</option>
<option value="5000">5K</option>
<option value="10000">10K</option>
<option value="25000">25K</option>
<option value="30000">30K</option>
<option value="50000">50K</option>
<option value="80467.2">50M</option>
<option value="100000">100K</option>
<option value="160934">100M</option>
</select>

<input id="distance"  type="text" name="distance" >
<select id="distanceUnit">
<option value="Kilometer">Kilometer</option>
<option value="Mile">Mile</option>
<option value="Meter">Meter</option>
</select>

</div>
</form>
</body>
</html>
``````
LVL 55
###### Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Owner (Aidellio)Commented:
Floating point arithmetic is what JavaScript uses.  Considered accurate to 15 decimal places.  Your calculation goes past that.
0
Owner (Aidellio)Commented:
Do you need that level of accuracy?
0
Owner (Aidellio)Commented:
// change
convr = Math.ceil(conv*1000)/1000;
to
convr = conv.toFixed(2);
1

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Commented:
The first modern Olympic Marathon was 26 mi 385 yd.

I can convert this perfectly to 42,194.988 meters with my HP-15C.

Wikipedia rounds this up to 42,195  which is an error of 1.2 cm   or   0.28 parts per million.

I can convert 42,194.988 meters  perfectly to  42.194988 km by moving the decimal point.

If you get 42.197 this is more than odd, it is wrong.

The magnitude of this error is remarkably   1.000E-06  or 0.00000100.

I think that this means that there is a real error (not a round off error) in the 6th digit of the hidden?? conversion factor.

1 inch = 0.0254 meters exactly.   It is possible to calculate the conversion factors for English and metric distances (or their reciprocals) perfectly with no round off error.
1
Owner (Aidellio)Commented:
It's a JavaScript issue: http://www.w3schools.com/js/js_numbers.asp

You were almost there with the *1000/1000. As you can see in the reference, the suggestion is to do the factor of ten multiplication at the time of initial calculation. I.e. At each conversion line
0
Commented:
You can restrict yourself to integer arithmetic.
This is a recommended approach for critical software from the days of microprocessors and assembly language.

Let your basic unit  ==>  1 micron  ==>  0.001 mm  ==>  0.000001 m

``````1 mm  =           1000 u
1 m   =      1,000,000 u
1 km  =  1,000,000,000 u

1 in  =        254,000 u
1 ft  =      3,048,000 u
1 mi  = 16,093,440,000 u

1 Marathon  =  421,949,880,000 u  <==  And this is still only 12 digits.

So you can take this about 1000x further, which would get you to the
moon with 1 micron precision.
``````
1
Developer & EE ModeratorAuthor Commented:
Thank you! Both are answers I was looking for.  I ended up with toFixed(3).  However, d-glitch's solution is brilliant.
0
Developer & EE ModeratorAuthor Commented:
I want to let you know if an update where I am using d-glitch's micron conversion and it works. However, the key is to not doing any rounding because that will of course mess things up especially going from miles to metric.  The work around would be to store and calculate on a hidden variable and display something rounded. I am sticking with keeping the raw value.  http://jsbin.com/codowocore/edit?html,js,output

``````\$(function() {

// select length of run
var currentMeasure = \$('select#distanceUnit option:selected').text(); // current distance unit (miles, meters)
\$('#distanceSelect').on('change', function() { // get the distance from drop down
var distanceSelect = \$('#distanceSelect').val();
var convertTo = \$('select#distanceUnit option:selected').text(); // convert from meters or what is currently selected to new measure
if (distanceSelect !== '') {
// convert distance to selected distance unit
var c = convert('Meter', convertTo, distanceSelect);
// place converted lenght in text box
\$('#distance').val(c);
}

});

// recalculate the distance measure if change unit of measure
\$('#distanceUnit').on('change', function() {

var currentDistance = \$('#distance').val();
var newMeasure = \$(this).val();

var newDistance = convert(currentMeasure, newMeasure, currentDistance);

\$('#distance').val(newDistance);
currentMeasure = newMeasure;

});

});

function convert(convertFrom, convertTo, dist) {
var conv;
switch (convertFrom + convertTo) {

// convert from meters
case 'MeterKilometer':
conv = dist * 1000000;
conv = conv / 1000000000;

break;
case 'MeterMile':
conv = dist * 1000000;
conv = conv / 1609344000;

break;
case 'MeterMeter':
conv = dist * 1;

break;

// convert from miles
case 'MileKilometer':
conv = dist * 1609344000;
conv = conv / 1000000000;
break;
case 'MileMile':
conv = dist * 1;
break;
case 'MileMeter':
conv = dist * 1609344000;
conv = conv / 1000000;
break;

// convert from kilometer
case 'KilometerKilometer':
conv = dist * 1;
break;

case 'KilometerMile':
conv = dist * 1000000000;
conv = conv / 1609344000;
break;
case 'KilometerMeter':
conv = dist * 1000000000;
conv = conv / 1000000;
break;

}

return conv;

}
``````
0
Developer & EE ModeratorAuthor Commented:
One other note, the conversion of microns and miles is off

1 mi  = 16,093,440,000 u is what is listed and
it should be
1 mi  = 1,609,344,000 u
1
Commented:
>>   the conversion of microns and miles is off  [by a factor of 10]

Sorry about that.  Java may good for 15 digits, but my HP-15C is only good for 9, so I was trying to keep track of the decimal point in my head.
0
###### It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.