2012-07-06 7 views
7

私は次の機能を持っています。C#isPowerOfは機能

私は、関数を呼び出す場合:私は16807を呼び出す場合

isPowerOf(25, 2) 

それは、5^2は25 に等しいので、trueを返します。しかし、7^5で、次の方法:本で

isPowerOf(16807, 5) 

を場合、 '7'が出力されますが、a == (int)aはfalseを返します。

お手伝いできますか?ありがとう!

+6

[すべてのコンピュータ科学者が浮動小数点演算について知っておくべきこと]への義務的なリンク(http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – AakashM

+1

誰もがより良い提案をするつもりです浮動小数点の比較、しかし、IMO問題の根源はここのアルゴリズムです。 – harold

答えて

6

丸め誤差のために小さなイプシロンを使用してみてください:

return Math.Abs(a - (int)a) < 0.0001; 

ハロルドが示唆したように、場合aをラウンドした方が良いであろうが3.99999ように、整数値よりもわずかに小さいことを起こる:

return Math.Abs(a - Math.Round(a)) < 0.0001; 
+0

今は動作しますが、どうしたらいいでしょう7!=(int)7? – Novak

+0

@GuyDavid:丸め誤差のため、得られる数値は7ではありませんが、それは7.000000001などです。 – Dani

+0

@Guy David try:Console.WriteLine((int)a); –

2

あなたはコードをデバッグしてから、あなたは最初の比較でそれを見ることができる場合:

isPowerOf(25, 2) 

ここでは、真の

を得る理由です5.0 == 5 =>を5.0 を保持していると第二isPowerOf(16807, 5)

7.0000000000000009

を保持し7.0000000000000009 != 7は=>あなたが偽になっているのでれます。そしてConsole.WriteLineを(a)は、/切り捨てdoubleを四捨五入し、唯一のあなたはダニの溶液中で

2

Math.Powのような最も近い値がdouble秒で動作するので、丸め誤差がに来る比較する必要がある理由である7

を示しています根を奪うときに遊ぶ。あなたは、正確なパワー見つけたことを確認したい場合は、次の

  • を最も近い整数
  • へのルート
  • ラウンド結果を抽出するために、現在のようにMath.Powを実行するには、この整数を上げますあなたが供給されたターゲットを取得することを確認してください。問題を解決
5

比較が提案されている権限を整数に上げたときにMath.Powintの範囲内の数値の正確ななりますが、ここで何が実際に問題だ浮動小数点はすべてに関与すべきでないということです。本質的に不正確な測定で行われる計算の近似ではなく、整数に関する質問に対する正確な回答が必要です。

他にどのようにこれを行うことができますか?頭に浮かぶ

最初の事はチートです:

double guess = Math.Pow(num, 1.0/power); 
return num == exponentiateBySquaring((int)guess, power) || 
     num == exponentiateBySquaring((int)Math.Ceil(guess), power); 
     // do NOT replace exponentiateBySquaring with Math.Pow 

それは限りguessが1未満オフになっているように動作します。しかし、常にその条件が満たされているわけではないので、あなたのインプットには常に効果があるという保証はありません。

だからここに頭に浮かぶ次のことです:バイナリ検索(あなたが最初の上部境界の検索バリアント)結果はnumに最も近いためexponentiateBySquaring(base, power)baseのために。最も近い答えがnumに等しい場合にのみ(これらは両方とも整数であるため、この比較はきれいです)、numpower第1乗です。オーバーフローがなければ(それはあってはならない)、それは常に動作するはずです。

+0

確かに、整数と浮動小数点数が別々の型になっている理由があります。 –