3

PHP5.3.5を使用します。これが他のバージョンでどのように機能するかわからない。

数字を保持する文字列を使用することについて混乱しています。たとえば、'0x4B0'または'1.2e3'。PHPがそのような文字列を処理する方法は、私には一貫していないようです。私だけですか?それともバグですか?または文書化されていない機能?それとも、ドキュメントに魔法の文章が欠けているだけですか?

<?php

echo $str = '0x4B0', PHP_EOL;
echo "is_numeric() -> ", var_dump(is_numeric($str)); // bool(true)
echo "*1           -> ", var_dump($str * 1);         // int(1200)
echo "(int)        -> ", var_dump((int)$str);        // int(0)
echo "(float)      -> ", var_dump((float)$str);      // float(0)
echo PHP_EOL;

echo $str = '1.2e3', PHP_EOL;
echo "is_numeric() -> ", var_dump(is_numeric($str)); // bool(true)
echo "*1           -> ", var_dump($str * 1);         // float(1200)
echo "(int)        -> ", var_dump((int)$str);        // int(1)
echo "(float)      -> ", var_dump((float)$str);      // float(1200)
echo PHP_EOL;

どちらの場合も、をis_numeric()返しますtrue。また、どちらの場合も、$str * 1文字列を解析して有効な数値を返します(ある場合は整数、別の場合は浮動小数点数)。

でキャストする(int)$str(float)$str、予期しない結果が得られます。

  • (int)$strいずれの場合も、数字の前にオプションの「+」または「-」を付けて、数字のみを解析できます。
  • (float)$strより高度で^[+-]?\d*(\.\d*)?(e[+-]?\d*)?、たとえば、オプションの「+」または「-」、オプションの数字、オプションの数字を含むオプションの小数点、オプションの「+」を含む「e」で構成されるオプションの指数などを解析できます。 「-」の後にオプションの数字が続きます。ただし、16進データでは失敗します。

関連ドキュメント:

  • is_numeric() -「16進表記(0xFF)も許可されますが、符号、小数、および指数部分がない場合のみ」と記述されています。文字列が数値データを保持しているかどうかをテストすることを目的とした関数がtrueを返す場合、PHPはそのような文字列を数値に変換できると期待しています。これはで機能するようです$str * 1が、キャストでは機能しません。なんで?
  • 整数への変換-「演算子、関数、または制御構造が整数引数を必要とする場合、値は自動的に変換されるため、ほとんどの場合、キャストは必要ありません」と述べています。$s * 10そのようなステートメントの後、私はと(int)$s * 10式の両方が同じように機能し、同じ結果を返すことを期待しています。ただし、例に示すように、これらの式の評価は異なります。
  • 文字列の数値への変換-「有効な数値データはオプションの符号であり、その後に1つ以上の数字(オプションで小数点を含む)が続き、その後にオプションの指数が続く」と記載されています。「指数」は「e」または「E」の後に数字が続きます。たとえば、1.2e3有効な数値データです。記号(「+」​​または「-」)は記載されていません。16進値については言及されていません。これは、で使用される「数値データ」の定義と競合しますis_numeric()。次に、「この変換の詳細については、strtod(3)のUnixマニュアルページを参照してください」という提案があり、man strtod追加の数値(HEX表記を含む)について説明しています。それで、これを読んだ後、1​​6進データは有効または無効な数値データであると思われますか?

それで...

  • is_numeric()文字列が数値として使用される場合、PHPが文字列を処理する方法との間に何らかの関係がありますか(または、むしろあるべきです) ?
  • なぜ(int)$s(float)$sそして$s * 1異なる働きをするのか、すなわち。$sis0x4B0または1.2e3?の場合、まったく異なる結果が得られます。
  • 0x4B0文字列がとしてまたはとして記述されている場合、文字列を数値に変換してその値を保持する方法はあります1.2e3か?floatval()HEXでまったく機能しない、HEXで機能するように設定するintval()必要があり、型キャストする必要があり、機能する場合もあれば機能しない場合もあるため、これらは有効なオプションではありません。変換というよりはデータ操作のように見えるので、私も考慮していません。私はネイティブソリューションを探しているので、この場合、自己作成関数も考慮されません。$base16(int)$str(float)$str$n *= 1;
4

3 に答える 3

3

直接キャストであり、実際にはまったく違いは(int)$strあり(float)$strません。どちらも、それぞれのタイプの数として解釈できる限り多くの文字を文字列から読み取ります。

「0x4B0」の場合、int-conversionは「0」(OK)を読み取り、次に「x」を読み取って停止します。これは、「x」を整数に変換できないためです。フロート変換についても同様です。

「1.2e3」の場合、int-conversionは「1」(OK)、次に「。」を読み取ります。そして停止します。float-conversionは、文字列全体を有効なfloat表記として認識します。

のような式の自動型認識は$str * 1、明示的なキャストよりも単純に柔軟性があります。明示的なキャストでは、整数と浮動小数点数は、基本的に、によって生成さ%iれた形式である必要があります。%fprintf

ただし、柔軟性を高めるために、明示的なcasts-to-intではなくintvalfloatvalを使用できるかもしれません。

最後に、あなたの質問は「16進データは有効な数値データか無効な数値データか」というものです。ぎこちないです。「16進データ」というものはありません。16進数は単なる基数です。できることは、「4B0」のような文字列を取得し、などを使用して、2から36までの任意の基数strtoulの整数として解析することです。 [申し訳ありませんが、それはBSでした。strtoulPHPにはありません。ただしintval、同等の機能があります。上記を参照してください。]

于 2011-06-22T11:20:56.997 に答える
2

intvalパラメータがゼロのときにoct/hexプレフィックスを認識するstrtolを使用するため、base

var_dump(intval('0xef'));     // int(0)
var_dump(intval('0xff', 0));  // int(255)
于 2011-06-22T12:43:59.407 に答える
1

is_numeric()と、文字列が数値として使用される場合のPHPの処理方法との間に何らかの関係がありますか(または、あるべきです)?

PHPには数値と呼ばれるデータ型はありません。この関数は、PHPで数値is_numeric()として解釈できるもののテストに近いものです。

このような数値の解釈に関する限り、+値の前にを追加すると、実際にはPHPが数値に変換します。

$int = +'0x4B0';
$float = +'1.2e3';

これは文字列のマニュアルで説明されています。文字列から数値への変換のセクションを探してください

演算子によってトリガーされるので、同じことを行う関数がPHPにある必要がある理由はわかりません。それは不必要でしょう。


内部的には、PHPは、数値を取得するために使用zendi_convert_scalar_to_numberするadd演算子(想定+)を呼び出す関数を使用します。is_numeric_string

文字列で使用すると、まったく同じ関数が内部的に呼び出されis_numeric()ます。

したがって、ネイティブ変換関数をトリガーするには、+演算子を使用します。これにより、数値の疑似型(intまたはfloat)が確実に返されます。

参照:/Zend/zend_operators.c ; /ext/standard/type.c

于 2011-06-22T11:35:09.803 に答える