5

次のコードは、true を返す場合と返さない場合があります。

さまざまな結果を引き起こしている可能性のあるものは何ですか?

0.00 文字列は JSON オブジェクトから取得されます。

(コード簡略化)

if(new Float("0.00")>0){
    // do something
}

編集:

私が持っているのは、ゼロ、ゼロ未満、またはゼロより大きいかどうかを判断したいいくつかのフロートです。値は、0.00、0.001、または -0.001 のようなものです。それらが正、負、またはゼロかどうかを判断するにはどうすればよいですか?

編集:

おそらく、値を取得する方法を明確にする必要があります。BigDecimal について読んで、それを無駄に使用しようとしたため、問題を引き起こしているのはまったく別の何かである可能性があります。

値は、次のコードを使用して JSON フィード (LT:0.000 の形式) から抽出されます。

price = new BigDecimal(stocksJSONArray.getJSONObject(i).getString("LT"));

次に、価格がゼロより大きいか小さいかをテストするために、次の条件ステートメントを使用しました。

if(price.compareTo(BigDecimal.ZERO)==1){
    // greater than zero
}
else if(price.compareTo(BigDecimal.ZERO)==-1){
    // less than zero
}

このコードは、JSON フィードから読み出された多くの値に対してループされます。結果から、ゼロの一部priceはゼロより大きいものとして処理され、一部はゼロ未満として処理されます。他の何かがここで問題を引き起こしているのではないかと疑っていますか?

また、データの精度に問題があるかどうかを確認するテストも行いました。だから私はこれをしました:

DecimalFormat frmt = new DecimalFormat("0.000000000000000000000000");
String formatted = frmt.format(stock.change);

そして、正と負として認識されたゼロの場合、そのトレース値はまだ0.0000000000000000000000000.000000000000000000000001またはそのようなものでした。

4

4 に答える 4

4

あなたの式は確実falseに Java の結果を生成します。

ただし、ゼロが、たとえば、-1 をプラスの無限大で割った結果であるとします。この場合、大まかに言うと -0.00 として内部的に表されます。状況によっては、(マイナス記号なしで) ゼロとして出力される場合もあれば、0.00 とは異なる動作をする場合もあります。

通常、浮動小数点数は整数と同じ方法で小なり比較できます。丸め誤差のリスクがありますが、ランダムな小さな値を加算または減算しても、その誤差は改善されません。対等比較で違います。

事実を再確認し、浮動小数点の動作についてもっと読むことをお勧めします。

編集:元の質問に答えるために、上記を大幅に単純化しています。質問の編集に答えるには、さらに深く掘り下げる必要があります。

浮動小数点数の操作では、入力の精度精度、および出力の望ましい精度を知り、考慮する必要があります。タスクが解決できる場合もあれば、そうでない場合もあります。入力の精度が、回答を生成するのに十分でない場合があります。

あなたの場合、精度は32ビットで、そのうち24ビットが仮数で8ビットが指数です。つまり、このデータ型は 0.001 と 0.00100001 を安全に区別しますが、0.001000001 とは区別しないことを意味します。

 System.out.println((float)0.001 < (float)0.001000001);

(キャストによる単精度比較を強制しないと、異なる結果が得られることに注意してください。その場合、計算は倍精度で行われ、数値は安全に区別されます - 数値をさらに近づけるまでは。)

したがって、精度はデータ型によって決まります。それほど正確ではありません。入力精度は、データ型とは何の関係もないため、多くの場合、精度よりも決定がはるかに困難です。ただし、精度は精度よりも優れていることはありません。

数学的な実数は、特定の浮動小数点型での表現可能性に関して 4 つの可能な状況で自分自身を見つけることができます。それらは、人間が読める 10 進数表記でリテラルとして発生したときに受け取るさまざまな処理に対応しています。

  • バイナリで正確に表現できる場合があります。たとえば、0 または 0.25 です。次に、整数が整数変数になるのと同じくらい正確です。
  • または、型の精度に対応する精度でおおよそ表現可能です。たとえば、1/3 または 0.1 または 0.001 です。これは、必要な指数が使用可能な指数ビットの数に収まる場合に発生しますが、数値のバイナリ展開が仮数よりも長いか、完全に無限である場合です。
  • または、大幅に歪んだ精度で近似的に表現可能です。これらは非正規数 (非正規数) です。それは不正確であるだけでなく、算術演算がクロールに遅くなる可能性があります。これは通常、正しい動作が文書化されており、立派な Java コンパイラでさえ、この種のリテラルを見て少し汗をかくかもしれませんが、これはバグです。
  • または、まったく収まらず、コンパイラはリテラルが大きすぎるとして拒否します。

したがって、あなたの場合、有効な入力は 0 (正確)、0.001 (概算)、および -0.001 (概算) の 3 つしかないため、問題を解決できます。 数値を 0 リテラル(ちなみにこれは正確です) と比較するだけで、期待されるブール値(完全に正確な出力) が常に得られます。

ただし、これは、リテラルから直接派生した入力に依存します。入力が 0.001、-0.001、および のいずれかである場合(float)1000 * (float)0.001 - 1、これは別の質問になり、たとえば次のように答えを得る必要があります。

if (-0.00001 < x && x < 0.00001) // then x is zero 

そして、これら 3 つの魔法の値だけでなく、あらゆる入力を許可し、入力の精度についての手がかりがない場合、それはミッション インポッシブルです。最後にゴミの数字があるように始まるリテラルでさえ、0.000000000...Javaコンパイラによって完全にニュートラルなゼロに変換されます。これが起こった後、正確で美しい0.00.アンダーフロー値にマイナス記号を追加すると発生します。3 つの異なる値ではなく、すべて同じ、不正確なゼロ、変数の同じビット パターンです。

于 2012-04-30T16:02:52.613 に答える
1

Math.signum() を使用して、値がゼロに等しいか、ゼロより小さいか、または大きいかを確認できます。

于 2012-04-30T19:13:46.810 に答える
1

フロートは不正確です。次のように、誤差の範囲を指定する必要があります。

float result = new Float("0.00");
float expected = 0;
if (Math.abs(result - expected) < 0.00001)
...
于 2012-04-30T15:54:35.590 に答える
0

私は私のものを少し違ったものにしました。私はセンサーが 1 の読み取り値を示すことを期待していました。これが私が思いついたものです。

double a = y1;
                if((a-0)<1){
                    a=(1-a)+a;
                }
于 2017-08-14T04:12:22.297 に答える