修复了转换分数的短PHP代码段,将分数转换为可读格式的计算问题


Fix for convert fraction short PHP snippet, issue with calculation converting a fraction to more readable format

这是一个问题,当它遇到像: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';
}

感谢

您应该将行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);
}

你可以这样使用它:减少分数('300/10')。's’;

还可以对链式分数的函数进行更多的推广(例如:"300/100/10")。如果你愿意的话,我可以发送一个实施方案。

告诉我为什么"while($token[0]%10==0&&$token[1]%10==0)"使用"while($token[0]%100==0)"会更好,因为两种方法似乎都可以正常

如果您尝试使用字符串"3000/10"作为每个实现的参数,则具有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,因此不会返回"30s"。1/30小于零(0.0333…),因此地板(1/30)=0。这就是它返回"1/0 s"的原因

如果使用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,它返回"30s"

它更好,因为它将与更多的投入一起工作。

但我建议您使用我实现的"reduceFraction"函数。

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

  • echo reduceFraction('3000/10');输出"300"
  • echo reduceFraction('300/10');输出"30"
  • echo reduceFraction('30/10');输出"3"
  • echo reduceFraction('3/10');输出"3/10"
  • echo reduceFraction('3/3');输出"1"
  • echo reduceFraction('222/444');输出"1/2"
  • echo reduceFraction('444/222');输出"2"