[PHP-users 28028] Re: 整数の下限

Yasuo Ohgaki yohgaki @ ohgaki.net
2006年 1月 4日 (水) 23:48:01 JST


大垣です。

SAISHO Kazuhiro wrote:
> オンラインマニュアルで学習中の税所です。
> いつもお世話になっております。
> 
> さて、内容的にFAQかと思いますが、
> うまく検索できませんでしたので質問させてください。
> 次の2行がどうしてなのかわかりません。
> 
> var_dump (-2147483647 - 1);  # int(-2147483648)
> var_dump (-2147483648    );  # float(-2147483648)
> 
> 環境は、PHP 4.4.0 / FreeBSD 5.4-STABLE です。
> 宜しくお願い致します。

こう言った場合の動作が気になるのであればソースを見るのが
一番簡単です。以下のコードはPHP 5.1.1のコードですが他のバー
ジョンでもこの部分は変わらないと思います。

> var_dump (-2147483647 - 1);  # int(-2147483648)
は

        if (op1->type == IS_LONG && op2->type == IS_LONG) {
                long lval = op1->value.lval - op2->value.lval;

                /* check for overflow by comparing sign bits */
                if ( (op1->value.lval & LONG_SIGN_MASK) != (op2->value.lval & LONG_SIGN_MASK)
                        && (op1->value.lval & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {

                        result->value.dval = (double) op1->value.lval - (double) op2->value.lval;
                        result->type = IS_DOUBLE;
                } else {
                        result->value.lval = lval;
                        result->type = IS_LONG;
                }
                return SUCCESS;
        }

となっているのでアンダーフローチェックに引っかからないです。

> var_dump (-2147483648    );  # float(-2147483648)
は

<ST_IN_SCRIPTING>{LNUM} {
        errno = 0;
        zendlval->value.lval = strtol(yytext, NULL, 0);
        if (errno == ERANGE) { /* overflow */
                zendlval->value.dval = zend_strtod(yytext, NULL);
                zendlval->type = IS_DOUBLE;
                return T_DNUMBER;
        } else {
                zendlval->type = IS_LONG;
                return T_LNUMBER;
        }
}

となっているのでERANGEがセットされているのでfloatになっているのだと思います。
お使いの環境では

strtol("-2147483648", NULL, 0)

でerrnoにERANGEが設定されるのだと思います。

-- 
Yasuo Ohgaki




PHP-users メーリングリストの案内