Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert mixed fraction string to float in PHP

I assumed there'd be an easy way in PHP to convert a string like 18 5/16 into the float 18.3125. I can't find a straightforward function to do it. Is there one, or do I need to write my own?

like image 806
TRiG Avatar asked Dec 21 '22 16:12

TRiG


2 Answers

I don't think such a function exists -- at least not bundled with PHP.

Writing a function that does this operation, if your string always have the same format, should not be too hard ; for example, I'd say that something like this should do the trick :

$str = '18 5/16';
var_dump(calc($str));

function calc($str) {
    $int = 0;
    $float = 0;
    $parts = explode(' ', $str);
    if (count($parts) >= 1) {
        $int = $parts[0];
    }
    if (count($parts) >= 2) {
        $float_str = $parts[1];
        list($top, $bottom) = explode('/', $float_str);
        $float = $top / $bottom;
    }
    return $int + $float;
}

Which will get you the following output :

float 18.3125


And you might get something shorter with a few regex ; something like this should do the trick, I suppose :

function calc($str) {
    if (preg_match('#(\d+)\s+(\d+)/(\d+)#', $str, $m)) {
        return $m[1] + $m[2] / $m[3];
    }
    return 0;
}



Else, not bundled in PHP, but already existing, maybe this class could help : Eval Math.

Disclaimer : I have not tested it -- so not quite sure it'll work in your specific situation.

like image 146
Pascal MARTIN Avatar answered Jan 12 '23 01:01

Pascal MARTIN


To expand on Pascal's example, here is a more robust solution that can handle fractions greater than 1 and less than 1.

function parseFraction(string $fraction): float 
{
  if(preg_match('#(\d+)\s+(\d+)/(\d+)#', $fraction, $m)) {
    return ($m[1] + $m[2] / $m[3]);
  } else if( preg_match('#(\d+)/(\d+)#', $fraction, $m) ) {
    return ($m[1] / $m[2]);
  }
  return (float)0;
}

Here is some basic test coverage, useful to integrate this code with phpunit

class FractionParserTest extends TestCase
{
  /**
   * < 1
   * @return void
   */
  public function testSimple(): void
  {
    $qty = '3/4';
    $res = parseFraction($qty);
    $this->assertEquals(0.75, $res);
  }

  /**
   * > 1
   * @return void
   */
  public function testComplex(): void
  {
    $qty = '18 5/16';
    $res = parseFraction($qty);
    $this->assertEquals(18.3125, $res);
  }
}
like image 38
Tim Williams Avatar answered Jan 12 '23 00:01

Tim Williams