3

プロジェクトを Python から C# に変換しているときに、構文ファミリにいくつかの興味深い違いがあることに気付きました。それでも、C#の比較演算子の異なる動作を理解して理解することができず、行き詰まりました。

この好奇心を治す過程で、私は C 構文ファミリーのいくつかの言語を検討しました。C, C++, C#, Java, Javascript.. 動作確認済み。これがどのように発生したかです:

Let a=2, b=3, c=4, d=5;

ここで、次の式を考えてみましょう。

a < a < a  // returns true
c < b < a  // returns true
c > b > a  // returns false
a < c > b  // returns false

右結合性が原因である場合、JavaScript の次のコードは次のように動作しないはずです。

console.info(a < false);   // returns false
console.info(a < a);       // returns false
console.info(a < a < a);   // returns true, as opposed to returning false

C/C++版はこちら

int main(){
    int a=2, b=3, c=4, d=5;

    printf("%s\n","false\0true"+6*(a < a < a));  // returns true
    printf("%s\n","false\0true"+6*(c < b < a));  // returns true
    printf("%s\n","false\0true"+6*(c > b > a));  // returns false
    printf("%s\n","false\0true"+6*(a < c > b));  // returns false

  return 0;
}

Python を除いて、どこで

a < a < a  // returns false
c < b < a  // returns false
c > b > a  // returns true
a < c > b  // returns true

C ファミリーの言語と Python で式の計算方法が異なる理由を説明できる人はいますか?

4

2 に答える 2

4

Python は入力のわずかな解釈を使用するため、次のようになります。

正式には、 ifa, b, c, ..., y, zが式でありop1, op2, ..., opN、比較演算子である場合、 thena op1 b op2 c ... y opN zは と同等ですがa op1 b and b op2 c and ... y opN z、各式が最大 1 回評価される点が異なります。

これは、行が次のように解釈されることを意味します

a < a < a = a < a and a < a // returns false
c < b < a = c < b and b < a // returns false
c > b > a = c > b and b > a // returns true
a < c > b = a < c and c > b // returns true

C スタイルの言語では、比較式はfalse(整数値 0) またはtrue(整数値 1) のいずれかに評価されます。したがって、Cでは次のように動作します

a < a < a = (a < a) < a = 0 < a  // returns true
c < b < a = (c < b) < a = 0 < a  // returns true
c > b > a = (c > b) > a = 1 > a // returns false
a < c > b = (a < c) > b = 0 > b // returns false

ほとんどすべての言語がブール値の戻り値を持つ演算子を定義することに注意してください。ただし、ブール値は暗黙的にゼロまたは 1 に変換できるため、上記の命題は依然として有効です。

// C++ example
struct myComparableObject{
    int data;
    bool operator<(const myComparableObject& o){
       return data < o.data;
    }
};

myComparableObject a, b;
a.data = 2;
b.data = 3;
int c = 5;

a < b; // true
a < c; // error, a cannot be converted to int / unknown operator
a.data < c; // true
a < b < c; // true, as this is equal to
           //   (a < b) < c = false < c = 0 < c

たとえば、JavaScript はToNumber2 つの非文字列オブジェクトを比較するために実際に使用します。[ ECMAScript p78、11.8.5 The Abstract Relational Comparison Algorithm]をToNumber(false)参照してくださいToNumber(true) === 1

とが値である比較x < yでは、 、、または[...]が生成されます。xytruefalseundefined

  • ToPrimitive(x, ヒント Number) を呼び出した結果を px とします。
  • py を ToPrimitive(y, ヒント Number) を呼び出した結果とします。

    1. Type(px) が String で Type(py) が String でない場合は、

      a.ToNumber(px) を呼び出した結果を nx とします。px と py はプリミティブ値であるため、評価順序は重要ではありません。
      b.ToNumber(py) を呼び出した結果を ny とします。
      c.nx が NaN の場合、undefined を返します。
      d.ny が NaN の場合、undefined を返します。
      e.nx と ny が同じ Number 値の場合、false を返します。
      f.nx が +0 で ny が -0 の場合、false を返します。
      g.nx が -0 で ny が +0 の場合、false を返します。
      h.nx が +infty の場合、false を返します。
      i.ny が +infty の場合、true を返します。
      j.ny が -infty の場合、false を返します。
      k.nx が -infty の場合、true を返します。
      l.nx の数学的値が ny の数学的値より小さい場合 —<em>これらの数学的値は両方とも有限であり、両方がゼロではないことに注意してください —<em>true を返します。それ以外の場合は false を返します。
于 2012-07-20T07:02:41.793 に答える
2

a < a < aのように評価されるため、どちらが true((a < a) < a)になる0 < aか (a >= 0 の場合)

以下を実行すると、最初の式が false に変わります。

int main(){
    int a=0, b=3, c=4, d=5;

    printf("%s\n","false\0true"+6*(a < a < a));  // returns false
    printf("%s\n","false\0true"+6*(c < b < a));  // returns true
    printf("%s\n","false\0true"+6*(c > b > a));  // returns false
    printf("%s\n","false\0true"+6*(a < c > b));  // returns false

  return 0;
}

一方、Python では、 にa < a < aなりa < a and a < aます。したがって、 の結果を比較していませんa < a。ステートメントに括弧を追加すると、C のような動作が再び得られます。

(a < a) < a  ## returns true
(c < b) < a  ## returns true
(c > b) > a  ## returns false
(a < c) > b  ## returns false
于 2012-07-20T07:04:03.837 に答える