なぜfloat / doubleが必要なのですか?


29

私はhttp://www.joelonsoftware.com/items/2011/06/27.htmlを見ていて、0.3ではなく0.3についてのJon Skeetのジョークを笑っていました。個人的には浮動小数点数/小数/倍数の問題は一度もありませんでしたが、6502を非常に早く学習し、ほとんどのプログラムで浮動小数点数を必要としなかったことを覚えています。私がそれを使用したのは、不正確な数値は問題なく、出力は画面用であり、(db、ファイルに)格納または依存されないグラフィックと数学のためだけでした。

私の質問は、あなたが通常どこでfloats / decimals / doubleを使用しているのですか?だから私はこれらの落とし穴に注意することを知っています。お金ではlongを使用し、セント単位で値を保存します。ゲーム内のオブジェクトの速度のために、intを追加し、ピクセルを移動する必要があるかどうかを知るために値を分割(またはビットシフト)します。(6502日でオブジェクトを移動しました。分割もフロートもありませんが、シフトがありました)。

だから私はほとんど興味がありました。


10
住宅ローンに支払う利息が12.6のままで、13にならないことが非常に重要なので、cos 13はとてもいいラウンド数です。
チャニ

1
「私は非常に早い段階で6502を学び、ほとんどのプログラムでフロートを必要としませんでした。オブジェクトの速度のために、intを追加し、値を除算してピクセルを移動するかどうかを判断します。」これらは、お金を長いセントとして表現することを除いて、現代の実践でこれらのタスクを達成する非常に珍しい方法です。
-jprete

コンピューターがミリセントを理解するのは良いことです。
タイラーマック

1
またはさらに、分数を使用できるのに小数を使用するのはなぜですか?
タイラーマック

6
@Scrooge-皮肉なことに、フロートで0.6を表すことはできません。
マーティンベケット

回答:


28

ほとんどの場合、整数よりも正確であるためです。

今はどうですか?「ゲーム内のオブジェクトの速度のために...」これはそのような場合の良い例です。弾丸のような非常に高速なオブジェクトが必要だとしましょう。整数の速度変数で動きを記述することができるようにするには、速度が整数変数の範囲内にあることを確認する必要があります。つまり、任意の細かいラスタを作成することはできません。

しかし、その後、時計の時針など、非常に遅いオブジェクトを記述することもできます。これは弾丸オブジェクトよりも約6桁遅いため、最初のld(10⁶)≈20ビットはゼロでありshort int、最初から型を除外します。さて、今日はlongどこにでもあるので、まだ快適な12ビットが残っています。しかし、それでも、クロック速度は小数点以下4桁まで正確になります。それは非常に良い時計ではありません...しかし、それはゲームのために確かに大丈夫です。ただ、ラスターをこれまでよりも粗くしたくないでしょう。

...いつか新しい、さらに高速なタイプのオブジェクトを導入したい場合に問題になります。「ヘッドルーム」は残っていません。

float型を選択するとどうなりますか?同じサイズの32ビットですが、すべてのオブジェクトに対して完全な24ビットの精度が得られます。つまり、時計は何年もの間、秒単位で同期を保つのに十分な精度を備えています。弾丸の精度はそれほど高くありませんが、とにかくほんの数秒間だけ「生きる」ので、持っていればまったく役に立ちません。そして、あなたが記述したい場合はあなたもはるかに高速にオブジェクトのトラブルのいずれかの種類に(なぜ光?いいえ問題の速さ)、またははるかに遅いものを得ることはありません。確かにゲームではそのようなことは必要ありませんが、物理シミュレーションでは必要になることがあります。

また、浮動小数点数を使用すると、常にこの同じ精度が得られます。最初に非自明なラスターを賢く選択する必要はありません。そのような選択の必要性は非常にエラーが発生しやすいため、これがおそらく最も重要なポイントです。


整数は完全に正確です。不正確さは、誤った計算によるものです。
-fjdumont

15
整数は、整数(ℤ)数を実際に表すために使用する場合にのみ完全に正確です。他のものを表すということは、実際、誤った計算を意味します。このような場合、2つの可能性があります。実際に表現したい数値に完全に適合するタイプを定義します。これは可能です。たとえばMathematicaで可能です。しかし、それは非常に複雑で時間のかかるものであり、実際には完全な精度を必要としないため、通常は努力する価値はありません。ただし、十分な精度が必要です。一般的に、整数よりも浮動小数点数の方が優れています。
leftaroundabout

53

離散値ではなく連続値を記述するときに使用します。それを説明するのはそれほど複雑ではありません。小数点付きの値が連続していると仮定するのを間違えないでください。ペニーを追加するなど、一度にまとめて変更する場合は、個別です。


28

ここには2つの質問があります。

とにかく、なぜ浮動小数点演算が必要なのですか?

Karl Bielefeldtが指摘するように、浮動小数点数を使用すると、物理的な世界だけでなく、ビジネスや金融のような場所でも、連続した量をモデル化できます。

私は、プログラミングキャリアの多くの多くの分野で浮動小数点演算を使用しました。化学、AutoCADでの作業、財務予測を行うためのモンテカルロシミュレーターの作成です。実際、David E. Shawという名前の男がいます。彼はウォール街に浮動小数点ベースの科学モデリング手法を適用して数十億ドルを稼いでいます。

そして、もちろん、コンピューターグラフィックスもあります。私はユーザーインターフェイスの見た目の美しさの開発について相談しますが、最近では浮動小数点、三角法、微積分、線形代数をしっかりと理解せずにそれをやろうとすると、ポケットナイフで銃撃戦をするようなものになります。

なぜ誰もがフロート対ダブルが必要なのでしょうか?

IEEE 754標準表現と、32ビット浮動小数点7小数精度の桁、および範囲内の指数10についてあなたを与える-38 10へ38。64ビットは、ダブル10の範囲の15進精度の桁数、および指数についてあなたを与える-307 10への307

誰もが合理的に必要とするものにはフロートで十分だと思われるかもしれませんが、そうではありません。たとえば、実世界の多くの数量は7桁以上の10進数で測定されます。

しかし、もっと微妙に、「ラウンドオフエラー」と口語的に呼ばれる問題があります。2進浮動小数点表現は、1 / 2、1 / 4、3 / 4など、分数部分の分母が2の累乗である値に対してのみ有効です。1/ 10などの他の分数を表すには、「丸め」ます最も近いバイナリ分数の値ですが、それは少し間違っています-それは「ラウンドオフエラー」です。その後、これらの不正確な数値を計算すると、結果の不正確さは最初の値よりもはるかに悪くなることがあります。エラーの割合が乗算されたり、指数関数的に積み重なることさえあります。

とにかく、処理する必要のあるバイナリ桁が多いほど、丸められたバイナリ表現は表現しようとしている数値に近くなるため、丸め誤差は小さくなります。その後、計算を行うときに、使用する数字が多い場合は、累積的な丸め誤差が問題のある場所に蓄積する前に、さらに多くの操作を行うことができます。

実際には、10進数の15桁の64ビットの倍精度は、多くのアプリケーションにとって十分ではありません。私は1985年に80ビットの浮動小数点数を使用していましたが、IEEEは現在、128ビット(16バイト)の浮動小数点型を定義しています。


2
ボブ+1天文学用の望遠鏡のような高解像度制御システムでの私の経験では、用語を並べ替えない限り、64ビットの倍精度では十分ではありません。消防と長距離航海
についても同様

20

これはよくある誤解です。お金を扱うすべての場所で、その値を整数(セント)として保存する必要があります。オンラインストアのようないくつかの単純なケースでは事実ですが、より高度なものを持っている場合はあまり役に立ちません。

たとえば、開発者が年間100,000ドルを稼いでいるとします。彼の正確な月給は何ですか?整数を使用すると、結果$ 8333.33(¢833333)が得られ、これに12を掛けると$ 99,999.96になります。整数としてそれを維持するのに役立ちましたか?いいえ、そうではありませんでした。

銀行は常に小数値/整数値を使用していますか?まあ、彼らはトランザクションの部分を行います。しかし、たとえば、実際の取引を追跡することを除いて、投資銀行業務について話し始めるとすぐに、他のすべては浮動小数点数になります。すべて社内コードなので、表示されませんが、本質的には同じであるQuantLibでピークを取ることができます(はるかにきれいな;-)。

なぜフロートを使用するのですか?平方根、対数、非整数の指数などのべき乗などの関数を使用している場合は、10進数を使用してもまったく役に立ちません。もちろん、浮動小数点数はDecimal型よりも高速です。


1
@Job-小数と浮動小数点数は大きく異なります。0.1は10進タイプに正確に格納できます、floatまたはdoubleに格納できません。
スコットホイットロック

3
別の質問がありました。$100,000/12フロートを支払って使用した場合。結果が正確に100,000ドルになるのはなぜですか?誰かが支払われるたびに、フロート(または小数)が切り上げまたは切り捨てられないのはなぜですか?小切手を書くとき(あなたは1/2または1/3セントを行うことはできません)または直接預金(私はそれが同じ制限があると仮定)について話している

@酸:>>> x = 100000 / 12.0 >>> x * 12 100000.0
vartec

コメントを読み直しますか?私の質問は、ソフトウェアを使用して毎月チェックを作成するときです。1/2セントは支払えないので、1年後にどのように全額を受け取ることができますか?

2
@acid:整数、小数、または除算を浮動小数点数として使用するかどうかに関係なく、ストレート除算は使用できません。これが全体のポイントです。小数を使用しても、その場合は役に立ちません。
バルテック

4

あなたが説明したことは、すべての入力と出力を制御する状況に最適な回避策です。

実際の言葉では、そうではありません。データを実際の値としてある程度の精度で提供し、データを同じ形式で返すことを期待するシステムに対処できる必要があります。このような場合には、あなたがなり、これらの問題が発生しました。

実際、リストしたトリックを使用しても、これらの問題が発生します。価格に対して17.5%の税を計算する場合、値をドルとして保存してもセントとして保存しても、小数セントが得られます。あなたが彼に十分に支払わないと税務人が非常に動揺するので、あなたは丸めを正しくしなければなりません。正しいmoneyタイプを使用すると(使用している言語の種類に関係なく)、苦痛の世界からあなたを救います。


お金の種類は何ですか?(言語または参照リンク)と「正しい」タイプはなぜですか?それは... 128ビット以上のものですか?私の「トリック」の使用が間違っているのはなぜですか?あなたはセントで整数を持っています。.175倍すると、整数が得られ、必要なものに使用できます。あなたの例を考えると、floatは十分な精度で私の値を保持できると思いますが、0.3f == 0.3dが偽であることを心配する必要はありません。

1
@ acidzombie24-特定のタイプを意味するわけではありませんが、お金の価値を表すためにあなたの言語が使用するタイプは何でも。また、10セントがあり、0.175を掛けると、1.75セントになります。整数演算でどのように対処しますか?1セントですか、それとも2セントですか?それを間違えると、あなたの顧客は税務署に多くのお金を所有することになります。
ChrisF

10(整数)に.175(実数/浮動小数点数)を掛けないでください。正確な数と不正確な数を混ぜてはいけません。結果は不正確になります。つまり、正確な数値のシステムでは、.175のような値は存在しないため、これは無意味な計算です。より良い解決策は、10000に175を掛け、必要に応じて手動で小数点を挿入することです。
バリーブラウン

8
@バリー-わかった。発生する問題の種類を説明しようとしていました。また、税率が17.5%で、10セントのアイテムの税を計算する必要がある場合、0.175などの値が存在します。
ChrisF

1
@acidzombie:お金に使用する正しい型は、高精度(少なくとも4小数点)の固定小数点です。ifs、ands、またはbutsはありません。貨幣の価値をセントとして保存するだけで十分ではありません。実際には2ポイントの精度しか得られないからです。
アーロンノート

3

「神が全数を創造した。他のすべては人間の仕事だ」–レオポルド・クロネッカー(1886)。

定義上、他の種類の数字は必要ありません。プログラミング言語のチューリング完全性は、さまざまな種類の数値間の単純な関係に基づいています。整数(a / k / a自然数)で作業できる場合は、何でもできます。

あなたはそれらを必要としないので、質問は一種の特別です。たぶん、あなたはそれが便利であるか、最適であるか、より安いか何かである場所を望みますか?


7
また、集合論演算と空集合のみを使用してそれらを構築できるため、整数を省くこともできます。しかし、それとチューリングの完全性からの論争は、両方とも極端な学術的還元主義です。
ボブマーフィー

4
また、チューリング完全性はコンピューティングにのみ適用されます。整数も有理数も数学的に完全ではありません。どちらもコーシー数列の収束に近いからです。だから、クロネッカーは熱気でいっぱいだった:あなたが全体の数字を含む完全な距離空間をしたい場合、あなたは本物の取得する必要があります:xkcd.com/849
ボブ・マーフィー

1
@ボブ・マーフィー:「アカデミックな還元主義は極端に進んだ」。正確に。質問は貧弱であり、可能な答えとしてこれにつながります。
S.Lott

2

文では、浮動小数点10進型は、整数値(コンピューターはバイナリレベルでの処理方法をすべて知っているため、バイナリ値に小数点はありません)との間の変換をカプセル化します。 10進数の計算のためのインターフェースを理解します。

率直に言って、整数を使用して10進数の計算を行う方法を知っているので、浮動小数点数は必要ないと言っているのは、算数の速記方法を知っていると言っているのに、なぜ電卓を使用するのですか?あなたは概念を知っています。ブラボー。常にその知識を行使しなければならないという意味ではありません。多くの場合、sig figを整数値に変換するのではなく、3.5 + 4.6 = 8.1と単純に言う方が、高速で、安価で、非バイナリウィズにとってより理解しやすいです。


1

浮動小数点型の主な利点は、実行時の観点から、大部分の計算目的で2つまたは3つの形式(80ビット形式をサポートするより多くの言語が必要)で十分であることです。プログラミング言語が固定小数点型のファミリを簡単にサポートできる場合、特定のレベルのパフォーマンスに必要なハードウェアの複雑さは、固定小数点型の方が浮動小数点よりも低いことがよくあります。残念ながら、そのようなサポートを提供することは「簡単」にはほど遠いです。

プログラミング言語がアプリケーションの数値的ニーズの98%を効率的に満たすためには、数十のタイプを含め、何百もの組み合わせの定義操作を提供する必要があります。さらに、たとえプログラミング言語がすばらしい固定小数点サポートを持っていたとしても、一部のアプリケーションでは、浮動小数点を必要とするために十分に大きな範囲にわたっておおよそ一定の相対精度を維持する必要があります。いずれにせよ、浮動小数点演算が必要になる場合があるため、ハードウェアベンダーが2つまたは3つの浮動小数点形式での数学のパフォーマンスに焦点を合わせ、コードが適切に機能する場合はいつでもこれらの形式を使用するようにすると、一般的に改善されます固定小数点演算の動作を最適化しようとするよりも、「大金」です。

ちなみに、固定小数点演算は、32ビットのプロセッサよりも8ビットおよび16ビットのプロセッサの方が有利でした。8ビットプロセッサでは、32ビットでは十分ではない状況で、40ビットタイプは、32ビットタイプよりも25%多くのスペースと25-50%多くの時間を費やし、37.5%を必要とします。 64ビットタイプよりも少ないスペースと37.5〜60%の時間。32ビットプラットフォームでは、32ビットタイプでは不十分な場合、64ビット未満のものを使用する理由はほとんどありません。48ビットの固定小数点型で十分な場合、64ビットの「double」は固定小数点型と同様に機能します。


0

一般的に、それらの使用には非常に注意する必要があります。単純な計算でさえ生じる精度の損失を理解することは困難です。たとえば、このような数字のリストを平均化することは非常に悪い考えです。

double average(List<Double> data) {
  double ans = 0;
  for(Double d : data) {
    ans += d;
  }
  return ans / data.size();
}

その理由は、リストが十分に大きい場合、十分に大きくなると基本的にすべてのデータポイントが失われるためですans(たとえば、これを参照)。このコードの問題は、小さなリストの場合はおそらく機能することです---壊れるのは規模が大きいだけです。

個人的には、次の場合にのみ使用すべきだと思います。a)計算が本当に高速でなければならない。b)結果が途方に暮れる可能性が高いことを気にしません(自分が何をしているのか本当にわかっていない限り)


-1

1つの考えは、整数範囲外の値を処理する必要がある場合は、floatまたはdouble表現を使用することです。

今日のアーキテクチャには、(おおよそ)+/- 2,147,483,647(32ビット)または+/- 9,223,372,036,854,775,807(64ビット)の符号付き整数範囲があります。符号なしは、それを2倍に拡張します。

IEEE 754フロートは(おおよそ)+/- 1.4×10 ^ −45から3.4×10 ^ 38になります。この範囲を+/- 5×10-324±2.225×10 ^ -308にダブル拡張すると、ここでは多くの条件と詳細が省略されます。

もちろん、最も驚くほど明白な理由は、-0を表す必要があるかもしれないことです;-)


主にウィキペディアの記事からの番号であり、説明のためのものです。-0を除き、それはただの楽しみです。
スティーブン

問題は、その巨大な範囲にまったく表されていない整数がたくさんあることです。
バリーブラウン

@BarryBrown絶対に正しい。「多くの条件と詳細は省略されました」。
スティーブン

-1

通常の理由は、JVMが一般的に基礎となるハードウェアサポートを使用しているため、高速であるためです(strictfpを使用しない場合)。

strictfpが意味するものについては、https: //stackoverflow.com/questions/517915/when-to-use-strictfp-keyword-in-javaを参照してください


浮動小数点演算は整数演算よりも高速ですか?浮動小数点計算は、どのプロセッサで整数計算よりも少ないサイクルで実行されますか?
this.josh

1
@ this.joshは、数字の桁数に強く依存します。また、整数は正確に除算できないため、重要な場合とそうでない場合があります。

-2

だからこそ256ビットのオペレーティングシステムが必要です。

プランクの長さ(測定可能な最小距離)= 10 ^ -35m
観測可能な宇宙は14Bnパーセック= 10 ^ 25mです
ので、精度が200ビットしかない場合は、プランクの長さの単位で整数として何でも測定できます。


2
-1:観測可能な宇宙よりも大きなスケールで物事をシミュレートしている場合はどうなりますか?
アマラ

2
@sparkleshy、それがFARポインターの目的です!
マーティンベケット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.