2009-05-15 15 views
0

は考える:どのようにして最良の正確な結果を得ることができますか?

unsigned int a, b, c, d; 

私が欲しい:

d = a * b/c; 

と(* b)がオーバーフローする可能性があり、また、(b/c)はゼロに等しく、正確性が低い。

おそらく64ビットにキャストすると動作するかもしれませんが、私はdで最も正確な結果を得るための最良の方法を知りたいと思います。

良い解決策はありますか?

+1

より多くを知らなくても、それは助言を与えることは難しいです。たぶん浮動小数点を使って問題を解決するには十分ですが、それらは独自の問題を伴います。本質的に、本当の問題についてもっと教えてください。 – lothar

+0

少なくとも、方程式が働くことを期待していた入力変数の範囲を教えてください。 – lothar

+0

指定された範囲はありません。すべてがunsigned intです。 bとcは100万を下回る可能性があります。 –

答えて

1

あなたの問題については、私はfloatに行くにd = (long long)a * b/c;

は意味しないと思います。すべてを再宣言したりキャストする必要はありません。鋳造aは、表現の中でより大きなサイズにbcを促進するのに十分です。

5

私はどちらかになります。

64ビットにキャスト
  • 、それは、a、b、およびcのあなたの範囲のために働くだろう場合。
  • あなたはそれらの結果が許容見つけた場合、floatまたはdoubleとバックにGMP
  • キャストのような無限の精度ライブラリを使用してください。
+2

GMPの提案のために+1 – lothar

+0

私はGMPがこの場合には少し過剰すぎると思います。 2つの32ビット整数を32ビット整数で割った値は、操作を実行する順序にかかわらず、64ビットを超えることはありません。 –

+0

良い点;その答えは、この特定の問題を解決する最も効率的な方法であるというよりも、OPの目をそのようなものに開放することを意図しています。あなたが言うように、これはひどく非効率的で、この1つのことをやりたければ大きな依存関係をもたらします。 –

0

なぜfloatまたはdoubleを使用しないのですか? float(Intelチップ上)は32ビットの浮動小数点数なので、操作に必ずしも64ビットは必要ないでしょうか?

+1

32ビット浮動小数点数では、dの可能な値は2^32以上であるため、ある精度は必ず失われます(浮動小数点数はdの範囲外の値を持ちますので、実際にはいくつかのビットの一部を無駄にしています)あなたが持っている)。 –

1

floatまたはdoubleを使用して、浮動小数点演算で、ゼロによる除算が許可され、結果が正または負の無限大

1

になりますあなたはいつも* Bのオーバーフローのための明示的なチェックを行うことができます。

long long e = (long long) a * (long long) b; 
if (e <= INT_MAX) { 
    d = e/c; 
} else { 
    d = a * (b/c); 
} 

もちろん、これは負でないa、b、cにのみ有効です。それらが陰性である場合は、INT_MINもチェックする必要があります。

[更新]あなたも大きいので、cで割ったときに低い精度を失い、Bのどちらをチェックできます。

if (a >= b) { 
    d = a/c * b; 
} else { 
    d = a * (b/c); 
} 
+0

d = a *(b/c)の場合、告発が失われることがあります。 –

+0

それでも、c> bの場合、d = a * 0(a * bがオーバーフローした場合)となるという問題があります。 –

+0

精度を最大限に高めるには、より多くのビットまたは浮動小数点型を使用する必要があります。私の理解では、質問者はintですべての操作を実行しながら、最も正確な結果を得る方法を知りたいと思っていました。 –

3

最高の精度/高精度のためにあなたがあなたの前にあなたの乗算を行うことをお勧めします分割する。あなたは両方のキャストは必要ありませんが、彼らは間違いなく、それは少し明確に

int64_t d = (int64_t) a * (int64_t) b; 
d /= c; 

:あなたが示すように、あなたはint型の2倍のビットで何かを使用したいと思います。

cが十分小さい場合、dはまだintより大きい場合があることに注意してください。それはあなたにとって問題かもしれません。もしそれが確実でなければ、最後にintにキャストすることができます。述べたように、あなただけ多くのビットを必要とするとき

+0

私はあなたが正しいと思います、私は分割する前に倍数にする必要があります –

+0

長いlongを使用しないで、特定のサイズ(例えば、stdint.hのC99のint64_tまたは独自のtypedefを行うことができない場合) – starblue

+0

@starblue:そのため、「あなたの環境に適したタイプを使用する」と言いましたが、私はC99のint64_tに慣れていませんでした。 (C99より前は誰もが独自の "n-bit int"型を定義しました)あなたが示唆したようにint64_tを使う答えを更新しました。ありがとう! –

0

は、私は次の線に沿って何かをしたい:

if(c){ 
    d = (long long)a * b; 
    d /= c; 
} 
else{ 
    // some error code because div by 0 is not allowed 
} 
関連する問題