Link to home
Start Free TrialLog in
Avatar of Scott Fell
Scott FellFlag for United States of America

asked on

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;

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

Open in new window


HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<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>

Open in new window

Avatar of Rob
Rob
Flag of Australia image

Floating point arithmetic is what JavaScript uses.  Considered accurate to 15 decimal places.  Your calculation goes past that.
Do you need that level of accuracy?
ASKER CERTIFIED SOLUTION
Avatar of Rob
Rob
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Scott Fell

ASKER

Thank you! Both are answers I was looking for.  I ended up with toFixed(3).  However, d-glitch's solution is brilliant.
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) {
    //alert(convertTo+convertFrom);
    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;

}

Open in new window

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
>>   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.