web-dev-qa-db-ja.com

2つの整数を除算するときに浮動小数点値を取得するにはどうすればよいですか? (PHP)

こんにちは、私は2つの整数(例:12/13)を除算しようとしていますが、常に10進数ではなく整数1を取得しています。

値をフロートする前に型キャストしてみましたが、成功しませんでした。

基本的に私が欲しいのは0.923のような10進数の結果です...

$x = 12;
$y = 13;
echo $value = $x / $y; //Would like to see 0.923 not 1
21
user1869257

通常の状況では、コードは浮動小数点値_0.923076_...を返す必要があります.

丸められた整数が表示される理由は、_ini setting_の_"precision"_を_0_に設定しているためである可能性があります。これを修正するには、_php.ini_を編集するか、ini_set("precision", 3);計算前のコードで。

これを回避する別の方法は BCmath を使用することです:

_echo $value=bcdiv($a, $b, 3);
_

さらに、拡張機能を使用しないもう1つの方法は、計算したい値に_1000_を掛けて_3 decimals_を乗算することにより、小さな数学のトリックを使用することです。
この方法では、_12000_を_13_で除算し、全体が_923_になります。1e3を掛けたので、最後の3つ前にコンマ/ドットを挿入します場所。

_function divideFloat($a, $b, $precision=3) {
    $a*=pow(10, $precision);
    $result=(int)($a / $b);
    if (strlen($result)==$precision) return '0.' . $result;
    else return preg_replace('/(\d{' . $precision . '})$/', '.\1', $result);
}
_

echo divideFloat($a, $b); // 0.923

15
CSᵠ
echo $value = $x / (float) $y;

変数$yを浮動小数点数としてキャストする場合、インタプリタは整数除算ではなく浮動小数点除算を使用します。

これは、2つの整数変数で整数除算を使用することがデフォルトの前提であるためです。

$y = 13.0(分母としてfloat変数)を使用した場合は異なります:結果は常にfloat数です

13
Raffaello

公式マニュアル PHP:Arithmetic Operators に明記されているように、PHPの除算は常に浮動小数点値を返すため、他のすべての答えは正しくありません。

実際、質問は間違っています。質問者から予想されたとおり、コードは0.923 ...を生成するはずです。

皮肉なことに、投票された回答(@ BulletProof47から来た)は、間違っていない(ただし、意味もない)唯一のその他の回答です。彼が何を考えていたかは誰にもわかりません。

興味のある方のために、phpで除算を行う基本的な関数はdiv_function、 にあります Zend/zend_operators.c、 下に示された:

ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
    zval op1_copy, op2_copy;
    int converted = 0;

    while (1) {
        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
            case TYPE_PAIR(IS_LONG, IS_LONG):
                if (Z_LVAL_P(op2) == 0) {
                    zend_error(E_WARNING, "Division by zero");
                    ZVAL_BOOL(result, 0);
                    return FAILURE;         /* division by zero */
                } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
                    /* Prevent overflow error/crash */
                    ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
                    return SUCCESS;
                }
                if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
                    ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
                } else {
                    ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
                }
                return SUCCESS;
    ...
3
felix021