ホームページ Java &#&チュートリアル Javaにおけるfloatと倍精度の損失の例の詳細な説明

Javaにおけるfloatと倍精度の損失の例の詳細な説明

Jun 28, 2017 am 11:38 AM
java 数値 浮動小数点 計算する 避ける

1.javaのint、float、long、doubleの値の範囲

[java] view plain copy

public class TestOutOfBound {

public static void main(String[] args) {

System.out . println(Integer.MAX_VALUE-(-Integer.MAX_VALUE)); //メモリ オーバーフロー

System.out.println(Integer.MAX_VALUE) //2 の 31 乗、約 20 億お金を使うには十分ではないかもしれません

System.out.println(Integer.MIN_VALUE); // 負の 2 の 31 乗

System.out.println(Long.MAX_VALUE) // 2 の 64 乗 -1; 19 桁、非常に大きく、安心してお金に使用できます

System.out.println(Long.MIN_VALUE); //負の 2 の 64 乗

System.out.println(Float.MAX_VALUE ; - 149 乗

System.out.println(Double.MAX_VALUE); //2 の 1024 乗 -1,308 桁、float 桁数の 10 倍、主に複雑な演算と天文演算に使用されます

System.out .println( Double.MIN_VALUE); //2 の -1074 乗

}

}

2. 浮動小数点数と倍精度の損失の問題

例:

[java] プレーン コピーの表示

例: double result = 1.0 - 0.9;

言うまでもなく、この結果は誰もが知っています、0.099999999999999998

なぜこの問題が発生するのでしょうか? なぜこの問題が発生するのかを分析してみましょう。 :

float 型と double 型は主に科学計算と工学計算用に設計されています。これらは 2 進浮動小数点演算を実行します。この演算は、広範囲の数値に対して高精度で高速な近似計算を提供するように慎重に設計されています。ただし、完全に正確な結果が得られるわけではないため、正確な計算には使用しないでください。 float 型と double 型は、金融操作には特に適していません。float 型や double 型では、0.1 やその他の 10 の負のべき乗を正確に表すことができないためです (実際、理由は非常に単純です。10 進数で正確に表現できるかどうか)。 1/3 はどうですか? 同じ 2 進法では 1/10 を正確に表現できません。

浮動小数点演算が正確であることはほとんどなく、精度で表現できる範囲を超える限りエラーが発生します。多くの場合、エラーは数値のサイズが原因ではなく、数値の精度が原因で発生します。したがって、生成される結果は、望ましい結果に近いものではありますが、同じではありません。正確な演算に float と double を使用する場合は特に注意してください。

それでは、浮動小数点演算が精度の低下を引き起こす理由を詳しく分析してみましょう。



[java] view plain copy

まず、次の 2 つの質問を理解する必要があります:

(1) 10 進整数を 2 進数に変換する方法

アルゴリズムは非常に複雑です単純。たとえば、11はバイナリ数として表されます。

11/2 = 5 1

5/2 = 2以上11 の 2 進数表現は (下から上に): 1011

ここで 1 つ述べておきたいのは、割り算後の結果が 0 になった時点で終わりです。皆さん、考えてみてください。整数の割り算は本当ですか。 2で最終的には0になりますか?つまり、すべての整数を 2 進数に変換するアルゴリズムは無限ループを続けるのでしょうか。決してそうではありません。整数は常に 2 進数で正確に表現できますが、10 進数は必ずしも表現できるとは限りません。

(2) 10進数を2進数に変換する方法

このアルゴリズムは、小数がなくなるまで 2 を掛けます。たとえば、0.9 は 2 進数で表されます。 *2=1.6 整数部分 1 を取り出します

0.6*2=1.2 整数部分 1 を取り出します

0.2*2=0.4 整数部分 0 を取り出します

integerパート0

0. 0.8*2 = 1.6整数パート1を取ります

0.6*2 = 1.2整数パート0

0.9のバイナリ表現は(上から下まで): 1100100100100... 注: 上記の計算プロセスはループするため、*2 は小数部分を削除できないため、アルゴリズムは無限に継続されます。明らかに、10 進数の 2 進数表現を正確に行うことが不可能な場合があります。実は、その理由は非常に単純で、1/3 は 10 進法で正確に表現できるのでしょうか。同様に、2 進法では 1/10 を正確に表現できません。これは、浮動小数点減算に「無尽蔵の」精度損失の問題がある理由も説明します。

3. 解決策 1:

小数点を自分で記録することを気にせず、値が大きくない場合は、int を使用するかどうかに関係なく、long や int などの基本的な型を使用できます。範囲サイズの欠点は、小数点を自分で処理しなければならないことです。最も明白な方法は、通貨の計算に元ではなくセントを使用することです (加算と減算のみが必要です)。

例:

[java] view plain copy

int resultInt = 10 - 9;

double result = (double) resultInt / 100;//最終的には小数点を自分で制御します

4. 2:

BigDecmal を使用し、構築パラメーターで String 型を使用する必要があります。

「Effective Java」という本に解決策が記載されています。この本では、float と double は科学計算または工学計算にのみ使用できることも指摘されています。ビジネス計算などの精密な計算では、java.math.BigDecimal を使用する必要があります。


BigDecimal クラスには 4 つのメソッドがあります。私たちが注目するのは、浮動小数点データの正確な計算に役立つメソッド、つまり

BigDecimal(double value) // double データを BigDecimal データに変換する

このアイデアは非常に優れています。シンプルです。まず BigDecimal(double value) メソッドを使用して double データを BigDecimal データに変換します。その後、通常どおり正確な計算を実行できます。計算が完了したら、割り切れない結果を四捨五入するなど、結果に対して何らかの処理を行うことができます。最後に、結果は BigDecimal データから double データに変換されます。

この考えは正しいですが、API の BigDecimal の詳細な説明を詳しく見てみると、正確な計算が必要な場合は double を直接使用することはできず、BigDecimal を構築するために String を使用する必要があることがわかります。したがって、BigDecimal クラスの別のメソッド、つまり、正確な計算を正しく完了するのに役立つ BigDecimal(String value) メソッドに注目し始めます。

// BigDecimal(String value) は String データを BigDecimal データに変換できます

ここで問題が発生します。想像してみてください。浮動小数点データの加算演算を実行したい場合、最初に 2 つの浮動小数点数を文字列データに変換し、次に BigDecimal (文字列値) を使用して BigDecimal を構築する必要があります。次に、そのうちの 1 つで add メソッドを呼び出し、もう 1 つをパラメーターとして渡し、操作の結果 (BigDecimal) を浮動小数点数に変換します。浮動小数点データを計算するたびにこれを実行する必要がある場合、そのような面倒なプロセスに耐えることができますか?少なくとも私には無理です。したがって、最良の方法は、クラスを作成し、そのクラス内でこれらの面倒な変換プロセスを完了することです。このように、浮動小数点データの計算を実行する必要がある場合は、このクラスを呼び出すだけで済みます。インターネット上の一部の専門家は、これらの変換操作を完了するためのツール クラス Arith を提供してくれました。これは、浮動小数点データの加算、減算、乗算、および除算演算を完了し、結果を丸めることができる次の静的メソッドを提供します。

public static double add(double v1,double v2)
public static double sub(double v1) ,double v2 )
public static double mul(double v1,double v2)
public static double div(double v1,double v2)
public static double div(double v1,double v2,intscale)
public static doubleround(double v,int スケール)

Arith のソース コードを以下に添付します。浮動小数点計算を実行したい場合は、Arith クラスをソース プログラムにインポートするだけで、上記の静的メソッドを使用できます。浮動小数点計算を正確に実行します。

付録: Arith ソースコード

[java] view plain copy

import java.math.BigDecimal;

/**

* Java の単純型は浮動小数点数に対して正確な演算を実行できないため、このユーティリティ クラスは加算、減算、乗算、除算、丸めなどの正確な浮動小数点演算を提供します。

*/

public class Arith{

//デフォルトの除算演算精度

private static Final int DEF_DIV_SCALE = 10;

//このクラスはインスタンス化できません

private Arith(){

}

/**

* 正確な加算演算を提供します。

*/

public static double add (double v1, double v2) {

bigDecimal b1 = new bigDecimal (double.tostring (v1)); Turn B1.add (B2) .doubleValue() }

/**

* 正確な減算演算を提供します。

*/ public static double sub(double v1、double v2){bigdecimal b1 = new bigdecimal(v1)); double mul(double v1 ,double v2){

BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2));

return b1.multiply(b2).doubleValue();  

}

/**

* (比較的) 正確な除算演算を提供します。無尽蔵の除算が発生した場合、計算は

* 小数点以下 10 桁まで正確になり、それ以降の数値は四捨五入されます。

*/

public static double div(double v1,double v2){

return div(v1,v2,DEF_DIV_SCALE);  

}

/**

* (比較的) 正確な除算演算を提供します。無尽蔵除算が発生した場合、精度はスケールパラメータ

* で指定され、それ以降の数値は四捨五入されます。

*/

public static double div(double v1,double v2,int scale){

if(scale<0){

throw new IllegalArgumentException(

"スケールは正の整数またはゼロでなければなりません)。  

}

BigDecimal b1 = new BigDecimal(Double.toString(v1));  

BigDecimal b2 = new BigDecimal(Double.toString(v2));  

return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();  

}

/**

* 正確な小数点以下の四捨五入処理を提供します。

* @param v 四捨五入する必要がある数値

*/

public static double round(double v,int scale){

if(scale<0){

throw new IllegalArgumentException(

「スケールは必ず必要です」正の整数またはゼロであること)。  

}

BigDecimal b = new BigDecimal(Double.toString(v));  

BigDecimal one = new BigDecimal("1");  

return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();  

}

};  

以上がJavaにおけるfloatと倍精度の損失の例の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Javaのアームストロング数 Javaのアームストロング数 Aug 30, 2024 pm 04:26 PM

Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

See all articles