ゼロを比較
問題
さて、浮動小数点について。同じに見える2つのゼロ(+0.0、-0.0)を比較するコードを6つの言語で試してみました。今回もやはり1つだけ出力結果が違うものがありました。それはどれでしょうか?
program Project1; {$APPTYPE CONSOLE} var a: Extended; begin a := 0.0; if a = -0.0 then Write('equal'); end.
#include <iostream> using namespace std; int main(int argc, char* argv[]) { double a = 0.0; if( a == -0.0 ) cout << "equal"; return 0; }
package project1; public class Project1 { public static void main(String[] args) { Double a = 0.0; if( a.equals(-0.0) ) System.out.print("equal"); } }
namespace project1 { public class Project1 { public static void Main() { double a = 0.0; if( a == -0.0 ) System.Console.Write("equal"); } } }
<?php $a = 0.0; if( $a == -0.0 ) echo 'equal'; ?>
a = 0.0 if a == -0.0 print "equal" end
解説
正解は「Java」。
Javaでは、期待した「equal」は出力されません。それ以外の言語では正しく「equal」が出力され、2つのゼロ(+0.0、-0.0)が等しいことが確認できます。一般的に、この2つのゼロ(+0.0、-0.0)は等しいと扱うのが自然だと思いますが、Javaはマイナスのゼロ「-0.0」に対応しています。
問題のコードがプリミティブ型の「double」ではなく、ラッパータイプの「java.lang.Doubleクラス」を利用している点に注目してください。java.lang.Doubleクラスのコンストラクタは、doubleの即値「-0.0」や文字列「”-0.0”」を特別な値として受け取ることができ、2つのゼロ(+0.0、-0.0)を区別することが可能です。
問題のコードはJava SE 5から導入されたボクシング変換を併用しているので、以下に示すようにJava SE 5以前のコードに置き換えて考えると分かりやすいでしょう。
Double a = new Double(+0.0); if( a.equals(new Double(-0.0)) ) System.out.print("equal");
もちろん、DoubleクラスのdoubleValue()メソッドを使って「equal」と出力することもできます。
Double a = new Double(+0.0); Double b = new Double(-0.0); if( a.doubleValue() == b.doubleValue() ) System.out.print("equal");