2017-03-03 4 views
0

私は、Javaの悪名高いDouble.toStringアルゴリズムの最適化に取り組んでいます。私はすでにFloat.toStringを書き換えて成功しています(速度が400%以上向上しました)。 Float.toStringのアルゴリズムをテストするのは簡単でした。なぜなら、卵を煮沸するのにかかった時間で、可能なすべての値をInteger.MIN_VALUEからInteger.MAX_VALUEにスローすることができるからです。Double.toStringアルゴリズムがすべての値に対して正しいことをどのように証明できますか?

しかし、同じ方法でDouble.toStringをテストすると、Long.MIN_VALUEからLong.MAX_VALUEまで反復処理する必要があります。私はすべてのスレッドでこのテストを開始し、残りの人生で実行することができました。

私はこのアルゴリズムをテストするときに、結果として得られるStringを取得し、java.lang.Double.toString(double d)の結果に対してString.equalsを呼び出すだけです。一致すれば、次の値に移動します。

このアルゴリズムを改良した主な点は、不要な精度をなくすことです。 Double.toStringが計算されると、これを行うために特殊なBigIntegerクラスが使用されます。しかし、私は重要でないビットをトリミングすることによって、パフォーマンスの大幅な向上を伴って同じ結果を得ることができることを発見しました。

私はテストを失敗せずにすべての値を128ビット(トリムビットをオフセットに置き換えて)でトリミングできますが、どのようにすべての値を反復することなくこれを証明できますか?

私は何を求めているのでしょうか?元のアルゴリズムの作成者は、あらゆる可能な入力をテストせずにアルゴリズムが正しいことを絶対確実に知っていましたか?

+1

浮動小数点は実数を表し、0と1の間には実際には**無限の**量があるので、あなたは「そしてそれは終わらないと言っています」と言うのは正しいです。より正確には、任意の2つの実数の間に**無限**の量の他の実数があります。 –

+0

これのもう一つの結果は、浮動小数点数はすべての実数を決して正しく表すことはできません。 floatに格納されている現在の値が0の後にほんのわずかな桁しかない場合、**重要ではない**ビットのみが存在し、バイナリを表すことができます。 0。1は1/10なので、バイナリで表示することはできません。 –

+1

実用的には、JavaではDouble.toStringに2^64の可能な入力があります。これらのいくつかは同じ値(NaN)に解決されます。半分は負です。負と有限の無限大、負と正のゼロがあります。わずかに変更されたLong.toStringアルゴリズムを使用して、いくつかの問題を解決できます。しかし、ほとんどの場合、(b/s)* 10^decExp = double valueのような値bとsを見つけることによって計算されます。小数指数は、必要に応じて見積もられ、調整されます。 – HesNotTheStig

答えて

2

私はそうではないと確信しています。

あなたはDouble#toStringのために書かれthe OpenJDK 8OpenJDK 9テストを見て、それからずっと...満足感を得ることができません。

効果的
/* 
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 
* 
* This code is free software; you can redistribute it and/or modify it 
* under the terms of the GNU General Public License version 2 only, as 
* published by the Free Software Foundation. 
* 
* This code is distributed in the hope that it will be useful, but WITHOUT 
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
* version 2 for more details (a copy is included in the LICENSE file that 
* accompanied this code). 
* 
* You should have received a copy of the GNU General Public License version 
* 2 along with this work; if not, write to the Free Software Foundation, 
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 
* 
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 
* or visit www.oracle.com if you need additional information or have any 
* questions. 
*/ 

/* 
* @test 
* @bug 4428022 
* @summary Tests for Double.toString 
* @author Andrew Haley <[email protected]> 
*/ 

public class ToString { 

    public static void main(String args[]) { 
     if (!Double.toString(0.001).equals("0.001")) 
      throw new RuntimeException("Double.toString(0.001) is not \"0.001\""); 
     if (!Double.toString(0.002).equals("0.002")) 
      throw new RuntimeException("Double.toString(0.001) is not \"0.002\""); 
    } 
} 

、彼らがやっているすべては例をテストしています。 toStringメソッドが"0.001""0.002"を正常に返すと正しく識別した場合。

このかもしれ浮動小数点数は、そのファッションの文字列に二重に変換しようとしている何のためのまともな酸試験だろう画分のこれらの種類を、ハンドリングで悪名高い悪いであるという事実に関係しています。基本をカバーするためのテストを作成したばかりです。

これから何とかしてください。他に何をテストしたいのか少し難しく思うことをお勧めします。このことから、エッジケースだけが捕捉されたように見える。あなた自身の最適化でそれを拡張したいかもしれません。

...これらのテストを(より良い方法で、あなたのことを気にして)自分のスイートに追加することも、最悪の考えではありません。彼らは'09年以降変わっていない。

+0

うわー....それはすべて彼らがテストしたことですか? これよりも有効なテストケースがかなりあります。たとえば、計算に完全に異なる処理を行う4つまたは5つの主要なサブケースがアルゴリズムに含まれていることはわかっています。これらすべてのケースをどのようにテストできますか?特にそれがテストされたことがほとんどないことを知ってもらうことは、自信がありません。 – HesNotTheStig

+0

さて、いいえ、私はあなたの信頼が、文字通り* Double * toString'のテストであることを見て、特に高くなるとは思わないでしょう。フォローアップに答えるには、これらのコンポーネントを直接テストします。それぞれのケースが処理するように設計されていることを考え、それらのケースをテストします。 – Makoto

関連する問題