1

ミリメートルを分数(インチ単位)に変換するphp関数が本当に必要です。

例えば:

16mm = 5/8 インチ
321mm = 12 41⁄64 インチ

PHPの例を高低で検索しましたが、完全に困惑しています。このようなものを構築した親切な魂がそこにあるでしょうか。

助けてくれてどうもありがとう!

4

2 に答える 2

1

簡単な部分は、ミリメートルからインチに変換することです–25.4で割るだけです。難しいのは、最も近い32番目(または16番目、64番目など)を見つけることです。

この回答の最後に、toMixedNumber()と呼ばれる関数を含めます。次のアルゴリズムに従います。

  • 浮動小数点値に目的の分母を掛けて、最も近い単位に丸めます。
  • 分母で割ります。商は整数部分で、余りは分子です。
  • 必要に応じて、分子と分母の両方を最大公約数(GCD)で除算することにより、小数部分を最小項に減らします。GCDは、ユークリッドのアルゴリズムを使用して計算できます。
  • 整数部分と小数部分を、必要に応じて「i」、「n / d」、または「in/d」形式の文字列としてフォーマットします。「in/d」の場合、小数部のマイナス記号をすべて削除します。

関数の使用は簡単です。

const MM_PER_IN = 25.4;
echo toMixedNumber(14 / MM_PER_IN, 32) . "\n"; // 9/16
echo toMixedNumber(55 / MM_PER_IN, 32) . "\n"; // 2 5/32
echo toMixedNumber(321 / MM_PER_IN, 32) . "\n"; // 12 5/8
echo toMixedNumber(321 / MM_PER_IN, 64) . "\n"; // 12 41/64

興味深いことに、分母が常に2の累乗である場合(あなたの場合のように)、最適化が可能になります。正の分子を持つ適切な2進分数の場合、分子の最下位の「1」ビットの値は、分子と分母のGCDです。

if ($reduce) {
    $gcd = $num & -$num;
    $num /= $gcd;
    $denom /= $gcd;
}

番号がsignedintのビットに1つしかないかどうかをチェックするために、革新的な方法のビットをいじるトリックを採用しました。私のコンピューターでは、関数が約20%高速化されます。(任意のビットの値がより重要なビットのすべての値の除数であり、分母の唯一の「1」ビットが分子のどのビットよりも重要であるため、これは機能します。)ただし、私はそれを含めないことを選択しました。


function toMixedNumber($arg, $denom, $reduce = true) {
    $num = round($arg * $denom);
    $int = (int)($num / $denom);
    $num %= $denom;

    if (!$num) {
        return "$int";
    }

    if ($reduce) {
        // Use Euclid's algorithm to find the GCD.
        $a = $num < 0 ? -$num : $num;
        $b = $denom;
        while ($b) {
            $t = $b;
            $b = $a % $t;
            $a = $t;
        }

        $num /= $a;
        $denom /= $a;
    }

    if ($int) {
        // Suppress minus sign in numerator; keep it only in the integer part.
        if ($num < 0) {
            $num *= -1; 
        }
        return "$int $num/$denom";
    }

    return "$num/$denom";
}

上記のサンプルコードのライセンス

于 2013-01-05T09:53:44.317 に答える