2

How do I convert "1 1/4" to 1.25?

I want to take user input and convert it to the logical numerical equivalent. I say logical because 2 R and R 2 need to be 2(has to do with measuring chiropractic adjustments). Everything worked until they needed to be able to use mixed fractions.

Is there a library for this?

The only number that does not work is "1 1/4" which is converted in error to "2.75".

    // Sample input
    var values = ["2.5", "1 1/4", "1/4", "2 R", "R 2"];

    function l(msg) {
        console.log(msg)
    }

    function toDecimal(x) {
        if (x.indexOf('/') != -1) {
            var parts = x.split(" ")
            var decParts = parts[1].split("/")
            return parseInt(parts[0], 10) + (parseInt(decParts[0], 10) / parseInt(decParts[1], 10))
        } else {
            return x
        }
    }

    function total_it_up(values){
        var total = 0,
            value = 0

        if(values === undefined)
            return 0

        $.each(values, function(index, value){
            value = value.replace(/[^0-9./]+/g, "")
            value = eval(value)
            l(value)
            total += parseFloat(value)
        })

        return total
    }

SOLUTION

    function toDecimal(x) {
        if (x.indexOf('/') != -1) {
            var parts = x.split(" ")
            var decParts;
            if (parts.length > 1) {
                decParts = parts[1].split("/");
            }
            else {
                decParts = parts[0].split("/");
                parts[0] = 0;
            }
            return parseInt(parts[0], 10) + (parseInt(decParts[0], 10) / parseInt(decParts[1], 10))
        } else {
            return x
        }
    }


    function total_it_up(values){
        var total = 0;

        if(values === undefined)
            return 0;

        $.each(values, function(index, value){
            total += parseFloat(toDecimal($.trim(value.replace(/[^0-9./ ]+/g, ""))));
        })

        return total;
    }
Michael J. Calkins
  • 32,082
  • 15
  • 62
  • 91
  • I'm not sure if there's a library for this already, but it should be fairly straightforward maths once you've split out the values. – Rory McCrossan Nov 02 '12 at 17:36
  • @rory I'm working on a simple function I'll post unless someone beats me to it. – Michael J. Calkins Nov 02 '12 at 17:38
  • your `toDecimal` works fine. http://jsfiddle.net/es7Gy/ – jbabey Nov 02 '12 at 17:40
  • 1
    I don't see where you ever call your toDecimal function, which, aside from a few safety checks, looks like it ought to work. Also why `eval`? eval is evil. – Matt Burland Nov 02 '12 at 17:42
  • possible duplicate of [Convert Fraction String to Decimal?](http://stackoverflow.com/questions/7142657/convert-fraction-string-to-decimal) – SpYk3HH Nov 02 '12 at 17:46
  • @MattBurland `eval` is evil IFF you're using it to evaluate user input. Otherwise, it's merely a bad idea. – Blazemonger Nov 02 '12 at 17:48
  • Also: please use semicolons to terminate each line of code. It'll cause you problems someday if you don't. – Blazemonger Nov 02 '12 at 17:49
  • 2
    @Blazemonger: true, but since the question states: "I want to take user input and convert it to the logical numerical equivalent." I stand by my comment. – Matt Burland Nov 02 '12 at 17:51
  • @blazemonger semi colons are optional in Javascript. http://mislav.uniqpath.com/2010/05/semicolons/ I'm converting their input to numbers so eval isn't a problem for injection. Unless you have a specific example. – Michael J. Calkins Nov 02 '12 at 17:57
  • Since you asked: http://stackoverflow.com/q/5397275/901048 -- but if nothing else, it makes your code more readable to other humans. – Blazemonger Nov 02 '12 at 18:07
  • @blazemonger That's all I needed to see :) What I'm doing now: http://jsfiddle.net/hcgGV/ I just get a split error but it parses everything correctly. – Michael J. Calkins Nov 02 '12 at 18:18
  • @SpYk3HH That other question isn't a duplicate, because it only handles a single fraction, not mixed fractions. – Barmar Nov 03 '12 at 04:17

3 Answers3

2

We don't see any call for toDecimal(), so I'm assuming the $.each loop is calling it in your original code. If that is the case, then 1 1/4 is coming up as 2.75 because the regular expression is stripping the space between 1 and 1/4, resulting in 11/4, which is 2.75. Allow spaces, but $.trim the result so that any leading or trailing spaces are removed. You also shouldn't have to use eval().

Mathachew
  • 2,044
  • 2
  • 18
  • 31
  • I'm going to go at this with each of the inputs one at a time I'll update my question with the answer when I get it. – Michael J. Calkins Nov 02 '12 at 17:59
  • Can you show us where exactly you're using `toDecimal()`? The only place I can see 2.75 occurring is when `value.replace(/[^0-9./]+/g, "")` is applied to the typed value, which turns `1 1/4` into `11/4`. Using `$.trim(value.replace(/[^0-9./ ]+/g, ""))` leaves `1 1/4` as is and will return the expected `1.25`. – Mathachew Nov 02 '12 at 18:04
  • Here's an example, with `toDecimal()` updated to properly handle `1/4`. Handling the various inputs could probably be better written, but it's a working example: http://jsfiddle.net/MVtnU/ – Mathachew Nov 02 '12 at 18:14
  • I think you pasted the wrong jsFiddle link. It has the same code I posted, and my update addresses the split error you're hitting (a space doesn't exist in `1/4`). – Mathachew Nov 02 '12 at 18:22
  • Have you looked at the jsFiddle link I posted? It fixes the error you're seeing. Your fiddle updated with the fix: http://jsfiddle.net/hcgGV/2/ – Mathachew Nov 02 '12 at 18:26
0

I accidently posted perl instead of JS before. Here is the correct one. Please do the cleaning.

Example

    <html>
  <body>
    <script language=javascript>


 var txt='4 1/2';

      var re1='(\\d+)'; // Integer Number 1
      var re2='.*?';    // Non-greedy match on filler
      var re3='(\\d+)'; // Integer Number 2
      var re4='.*?';    // Non-greedy match on filler
      var re5='(\\d+)'; // Integer Number 3

      var p = new RegExp(re1+re2+re3+re4+re5,["i"]);
      var m = p.exec(txt);
      if (m != null)
      {
          var int1=m[1];
          var int2=m[2];
          var int3=m[3];
          document.write("("+int1.replace(/</,"&lt;")+")"+"("+int2.replace(/</,"&lt;")+")"+"("+int3.replace(/</,"&lt;")+")"+"\n");
      }
    </script>
  </body>
</html>
srijan
  • 1,504
  • 1
  • 13
  • 24
0

This is terrible.

function ConvertFraction(fraction)
{
     eval(fraction.replace('R','').trim().replace(' ', '+'))
}
Porco
  • 4,163
  • 3
  • 22
  • 25