

１の補数を使う処理系にて、整数型の `-0` と `+0` は等しいのでしょうか？

以下 `int` 型を仮定します。  
負の０すなわち内部表現 `1111<中略>1111` である変数 `negative_zero` と  
正の０すなわち内部表現 `0000<中略>0000` である変数 `positive_zero` があるとき

`negative_zero == positive_zero` は真か偽か？  
`negative_zero != positive_zero` は真か偽か？  
`negative_zero < positive_zero` は真か偽か？

ISO/IEC 14882:1998 をチラ見した範囲でははっきりとした規定が見つかりませんでした。

浮動小数点数 `IEEE754` では `-0.0 == +0.0` なわけですが・・・


CC BY-SA 3.0
2016-06-27T05:19:57.660
27105
2019-11-02T03:49:58.980
2016-06-29T04:15:47.027
8589
8589
question
c++ c
１の補数系で -0 と +0 は等しいか


C/C++のコンパイラがある1の補数なシステムってあるのでしょうか?  
昔のUNIVAC1100系だと命令セットのTestEqual(==)/TestNotEqual(!=)は単純なビット比較なので-0と0は等しく **ない**
です。代わり（？）にゼロかを確認する専用の命令TestZero/TestNonZeroでは-0/+0ともに同じ扱いです。

まとめると  
`+0 == -0`:偽  
`+0 != -0`:真  
`+0 > -0`:真

ソース（データシートとかではないです）：[Minus
Zero](https://www.fourmilab.ch/documents/univac/minuszero.html)、[UNIVAC1100
Instruction Set](https://www.fourmilab.ch/documents/univac/instructions.html)


CC BY-SA 3.0
2016-06-28T12:45:41.183
27144
2016-06-28T12:45:41.183
3974
27105
answer


具体的なアーキテクチャではなく標準仕様 (ANSI/ISO C) の話として答えると、 `-0` と `+0` が等しいという規定は無いように思います。

1の補数系 (や、符号+絶対値) を利用するアーキテクチャでも `-0` をサポートしない可能性があること (その場合はトラップ表現扱い)、`-0`
は通常の演算結果としては発生しない (ビット演算などで無理矢理作り出すしかない) こと、ビット演算を利用しても必ずしも `-0`
が生成されないこと、生成された場合でも変数に格納した時点で `+0` に変換される可能性があることから、積極的に利用する機能では無さそうです。


CC BY-SA 3.0
2016-06-28T14:27:46.583
27151
2016-06-28T14:27:46.583
76
27105
answer


JIS X 3014:2003 ( [c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") 言語規格書)
にて

> 3.9 型  
>  ４項の注釈 *37  
>  この規定は [c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") のメモリモデルを JIS X
> 3010 と互換にすることを意図している

という文書を見つけたので JIS X 3010 を読んでみました。

JIS X 3010:2003 ( [c](/questions/tagged/c "'c' のタグが付いた質問を表示") 言語規格書)
にて次の解説を見つけました。部分引用します。

> 6.2.6.2 整数型  
>  符号ビットが１ですべての値ビットが０である数（符号と絶対値若しくは２の補数の場合）、  
>  または符号ビットが１ですべての値ビットが１である値（１の補数の場合）  
>  が、トラップ表現であるか又は通常の値であるかも処理系定義とする。
>
> [符号と絶対値または１の補数の場合] この表現が通常の値であるならば、これを負の０と呼ぶ。
>
> [処理系が負の０をサポートする場合に、演算が]  
>  実際に負の０を生成するか、又は通常の０を生成するかは未規定とする。  
>  負の０がオブジェクトに格納されるとき通常の０になるかどうかも未規定とする。
>
> [処理系が負の０をサポートしない場合] 負の０を生成する演算の結果は未定義とする。

（これらに相当する解説を JIS X 3014:2003 中で見つけることができませんでした）  
（ [c++11](/questions/tagged/c%2b%2b11 "'c++11' のタグが付いた質問を表示") や
[c++14](/questions/tagged/c%2b%2b14 "'c++14' のタグが付いた質問を表示") には解説あるのでしょうか？）

そもそも負の０がトラップ表現や未定義になるのであれば「使っちゃいけない」のであって、  
比較すること以前の問題なようです。

実在する１の補数を使う処理系 ([c](/questions/tagged/c "'c' のタグが付いた質問を表示") が実装されているかはおいといて)
では  
整数型の一致比較は既に回答のあるとおり「ビットパターンの一致比較」で実装されていると思うので  
`-0 != +0` は真 `-0 == +0` は偽、と考えてほぼ間違いないようです。  
`-0 < +0` はこれだけだと微妙ですが符号ビットが違うので真になると期待したいところです。  
（「未定義」の動作の中には「プログラマが勝手に期待するとおりの動作」も含まれますし）

まあ今時１の補数を使う処理系がどれだけ存在するか、実用されるかは定かではありませんが。  
オイラも実用したことはありませんし  
[コンピュータ内では2の補数が使われていますか1の補数が使われていますか](https://ja.stackoverflow.com/questions/12855/)


CC BY-SA 3.0
2016-06-29T01:44:03.460
27163
2016-06-30T04:41:29.467
2017-04-13T12:52:38.920
-1
8589
27105
answer


C11仕様書最終ドラフト [N1570](http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) を確認しました。

> 6.5.9 Equality operators (p.96)  
>  ...  
>  Semantics  
>  3 The == (equal to) and != (not equal to) operators are analogous to the
> relational operators except for their lower precedence.108) Each of the
> operators yields 1 if the specified relation is true and 0 if it is false.
> The result has type int. For any pair of operands, exactly one of the
> relations is true.

とだけあり、指定された関係(the specified relation)が真なら1、偽なら0としか規定されていません。つまり、
_ビット列が同じであれば必ず真(逆に言うとビット列が違っていれば必ず偽)ということではありません。_ この **関係**
とは何かということは具体的には次の所で言及されています。

> 7.12.14 Comparison macros (p.259)  
>  1 The relational and equality operators support the usual mathematical
> relationships between numeric values. For any ordered pair of numeric values
> exactly one of the relationships — less, greater, and equal — is true.

関係演算子と等価演算子は **通常の数学的関係** (the usual mathematical
relationships)をサポートしているとしています。(上の引用文の後にNaNに対する言及があります。)

上記のことから、C11における`==`及び`!=`は数学的関係における等価と同じとなっています。そのため、浮動小数点数における`+0.0`と`-0.0`は等しいとなっています(これはC11がIEEE754を採用しているからではなく、C11がIEEE754をそのまま採用できる浮動小数点数を規定しているだけに過ぎません)。これと同様に、1の補数系での`+0`と`-0`は数学的に等しいと考えら、`==`は真、`!=`は偽になると推測されます。

C++については確認していません。1の補数系である処理系が手元にないため、実際にそうなのまではわかりません。正式な仕様書[ISO/IEC
9899:2011](http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=57853)は持っていないので、そこまでは確認できていません。


CC BY-SA 3.0
2016-06-29T20:21:58.667
27200
2016-06-29T20:21:58.667
7347
27105
answer


本家 stackoverflow を検索してみました。  
<https://stackoverflow.com/questions/34148992/>

元質問が `int negzero = -0;` と書いてありそりゃただの(正の)ゼロだろと突っ込みが入って  
そっち系の回答にチェックが付いてしまっています。  
が、チェックの無い Serge Bastella 氏の回答のほうが今回オイラの求めているものに近いはずで  
それによると

> ISO/IEC 9899:<不明>  
>  6.2.6.2 処理系が負の０を生成するのは次に示す演算の場合に限られなければならない  
>  \- 負の０を生成するオペランドを伴った (snip) 演算子  
>  \- 一方のオペランドが負の０で、結果が０となる (snip) 演算子  
>  \- 上に掲げた２つの場合に基づく複合代入演算子

である以上

[code]

    std::cout << (1 << negzero) << std::endl;
    std::cout << (1 >> negzero) << std::endl;
    
[/code]

は「式が０を生成しない」がゆえに負の０も正の０と同じ振る舞いをし `1` 以外にはならない。

[code]

    std::cout<<(~negzero)<<(~zero)<<std::endl;
    
[/code]

は詰め物ビットがあっても良いという規定により処理系定義

[code]

    std::cout<<(negzero < zero)<<std::endl;
    std::cout<<(negzero <= zero)<<std::endl;
    std::cout<<(negzero == zero)<<std::endl;
    
[/code]

は（規格書から明確な文言を探しきれなかったので）処理系定義

という意見が述べられています。

オイラ的には文言「処理系定義」は言語規格書にそう明示されている場合に限ると解釈しているので  
後者２つは「未規定」であると思うところです。

* * *

JIS X 3010:2003, ISO/IEC 9899:1999 の 7.12 には

> 整数算術関数および文字列変換関数は 7.20 で規定する

とあります。  
`C11` ドラフトの `later` の文言は「採択版で章番号が決定したらそれに書き直す」程度の意図で、  
やはりこの章 7.12 は整数に関しては対象外な気がします。

LIA-1 についてはまだ検証していません。


CC BY-SA 3.0
2016-07-04T05:56:38.630
27320
2016-07-04T05:56:38.630
2017-05-23T12:38:55.307
-1
8589
27105
answer


今更ですが

古いCも含めて考えると、C言語が元々アセンブラの薄いラッパー(wrapper)で、処理系定義が基本的な考え方として考えると、1の補数処理系でもCPUの比較命令(x86で言うCMP)の結果そのものが使われると思います。なので、使うCの世代の仕様(コンパイラの仕様書)を見てはっきりしない時は使うCPUの仕様を見た方が確実かも知れません。


CC BY-SA 4.0
2019-11-02T00:53:31.413
60196
2019-11-02T00:53:31.413
36452
27105
answer


C++20では[符号付き整数型が2の補数表現であることを規定](https://cpprefjp.github.io/lang/cpp20/signed_integers_are_twos_complement.html)されました。C++言語では１の補数を使う処理系がサポートされなくなりました。


CC BY-SA 4.0
2019-11-02T03:49:58.980
60201
2019-11-02T03:49:58.980
4236
27105
answer