修复转换分数短PHP片段,计算将分数转换为更易读的格式

时间:2014-10-08 19:41:51

标签: php arrays token explode fractions

这是问题,当它遇到像:300/10这样的分数而不是给出“30”的结果 以下代码给出了我:1/0

$tokens = explode('/', $value);
while ($tokens[0] % 10 == 0) {
   $tokens[0] = $tokens[0] / 10;
   $tokens[1] = $tokens[1] / 10;
}
if ($tokens[1] == 1) {
   return $tokens[0].' s';
} else {
  return '1/'.floor(1/($tokens[0]/$tokens[1])).' s';
   // return $tokens[0].'/'.$tokens[1].' s';
}

谢谢

2 个答案:

答案 0 :(得分:0)

您应该将行while($tokens[0] % 10 === 0 && $tokens[1] % 10 === 0) {更改为while($tokens[0] % 10 === 0 && $tokens[1] % 10 === 0) {

return '1/'.floor(1/($tokens[0]/$tokens[1])).' s';不可靠。

如果您想减少分数,请尝试以下函数:

function reduceFraction($fraction) {
    sscanf($fraction, '%d/%d %s', $numerator, $denominator, $junk);

    // TODO: validation

    if( $denominator === null ) {
        return (string)$numerator;
    }

    if( $numerator === $denominator ) {
        return 1;
    }

    $max = max(array($numerator, $denominator));
    for($i = 1; $i < $max; ++$i) {
        if( $denominator % $i === 0 && $numerator % $i === 0) {
            $common = $i;
        }
    }

    if( $denominator === $common ) {
        return (string)($numerator / $common);
    }

    return ($numerator / $common) . '/' . ($denominator / $common);
}

您可以像这样使用它:     reduceFraction('300/10')。 's';

也可以概括更多链式分数的函数(例如:'300/100/10')。如果你愿意,我可以发送它的实现。

答案 1 :(得分:0)

  

告诉我为什么&#34; while($ tokens [0]%10 == 0&amp;&amp; $ tokens [1]%10 == 0)&#34;   最好是使用而不仅仅是#34;而($ tokens [0]%100 == 0)&#34;以来   这两种方法似乎都运行正常

如果您尝试使用字符串&#34; 3000/10&#34;作为每个实现的参数,具有while ($tokens[0] % 10 == 0 && $tokens[1] % 10 ==0)的那个将返回300 s,而另一个while ($tokens[0] % 100 == 0)将返回1/0 s

如果使用while ($tokens[0] % 100 == 0)方法,则循环迭代为:

  1. $tokens[0] = 3000 / 10 = 300; $tokens[1] = 10 / 10 = 10;
  2. $tokens[0] = 30 / 10 = 30; $tokens[1] = 10 / 1 = .1; 停止因为30%100!= 0。 由于$ token [1]不是1,因此它不返回&#34; 30 s&#34;。 1/30小于零(0.0333 ...),因此floor(1/30)= 0.这就是为什么它返回&#34; 1/0 s&#34;。
  3. 如果使用while ($tokens[0] % 10 == 0 && $tokens[1] % 10 == 0)方法,则循环迭代为:

    1. $tokens[0] = 3000 / 10 = 300; $tokens[1] = 10 / 10 = 1; 因为1%10!= 0而停止。 由于$ token [1]不是1,因此它返回&#34; 30 s&#34;。
    2. 它更好,因为它可以使用更多输入。

      但我建议你使用&#34; reduceFraction&#34;我实施的功能。

      它使用最大公分母技术来减少函数。

      • echo reduceFraction('3000/10');输出&#34; 300&#34;。
      • echo reduceFraction('300/10');输出&#34; 30&#34;。
      • echo reduceFraction('30/10');输出&#34; 3&#34;。
      • echo reduceFraction('3/10');输出&#34; 3/10&#34;。
      • echo reduceFraction('3/3');输出&#34; 1&#34;。
      • echo reduceFraction('222/444');输出&#34; 1/2&#34;。
      • echo reduceFraction('444/222');输出&#34; 2&#34;。