2012-07-06 22 views
7

sonraki fonksiyonu var.C# isPowerOf işlevi

ben işlevini çağırırsanız: Ben 16807 çağırırsanız

isPowerOf(25, 2) 

Bu 5^2 25. eşittir beri return true Ama 7^5 olduğunu sonraki yol: Bu ise

isPowerOf(16807, 5) 

durumda, '7' yazdırır, ancak a == (int)a yanlış döndürür.

Yardımcı olabilir misiniz? Teşekkürler!

+6

[Her Bilgisayar Bilimcinin Kayan Nokta Aritmetiği Hakkında Bilmeniz Gerekenler] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – AakashM

+1

Herkes daha iyi önerecektir kayan nokta karşılaştırmaları, ancak IMO sorunun kökünü burada algoritmadır. – harold

cevap

6

yuvarlama hataları için küçük epsilonu kullanmayı deneyin:

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

Harold önerilen olarak
return Math.Abs(a - (int)a) < 0.0001; 

, durumda a yılında yuvarlamak daha iyi olacak, tamsayı değeri biraz daha küçük olması 3,99999 gibi olur

+0

Şimdi çalışıyor ama nasıl 7! = (Int) 7? – Novak

+0

@GuyDavid: Yuvarlama hataları nedeniyle, sahip olduğunuz sayı 7 değil, ancak 7.000000001 veya – Dani

+0

@Guy David denen bir şey: Console.WriteLine ((int) a); –

2

kodu hata ayıklama ve sonra ilk kıyasla bu görebiliyorsanız:

isPowerOf(25, 2) 

bir tutan 5.0 İşte 5.0 == 5 => Eğer

gerçek olsun bu yüzden ve 2. isPowerOf(16807, 5)

bir

ve 7.0000000000000009 != 7 beri => false alıyorsanız 7.0000000000000009 düzenliyor. ve Console.WriteLine (a) çift yuvarlama ve sadece

2

Math.Powdouble s çalışır Dani'nın çözeltide gibi en yakın değeri karşılaştırmak gerekir yüzden bu 7

göstermek/kısaltılıyor, bu nedenle yuvarlama hataları girer Kök alırken oyna. Eğer kesin bir güce buldum olmadığını kontrol etmek istiyorsanız:

  • kök
  • yuvarlak ayıklamak için, hem halen Math.Pow gerçekleştirmek en yakın tam sayıya
  • zam için bu tamsayı için sonuç Sağlanan güç ve verilen hedefi aldığınızı kontrol edin. Sorunu çözmek
5

Karşılaştırmalar önerilmiştir güçler tamsayı yükselterek zaman Math.Powint aralığında sayılar için kesin olacak, ama burada ne aslında problem kayan nokta her de dahil edilmemelidir olmasıdır. Tamsayılarla ilgili bir soruyu tam olarak yanıtlamak istiyorsunuz, doğal olarak yanlış ölçümler üzerinde yapılan hesaplamaların bir yaklaşımı değil.

Peki bu nasıl yapılabilir?

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 

Bu sürece guess 1 kapalı azdır şekilde çalışmaya devam eder:

akla gelen ilk şey bir hile olduğunu. Ancak, her zaman sizin girdileriniz için çalışacağını garanti edemem çünkü bu koşul her zaman karşılanmaz.

Yani burada akla gelen bir sonraki şey: exponentiateBySquaring(base, power) yılında base için ikili arama (önce üst sınırından arama varyant) olan sonuç num en yakın olanı. En yakın yanıt num'a eşitse ve (ve her ikisi de tamsayıysa, bu karşılaştırma temiz kalırsa) ve ardından num bir power -th gücüdür. Taşma olmadığı sürece (olmamalı), bu her zaman çalışmalıdır.

+0

Evet, tamsayıların ve kayan nokta sayılarının ayrı türler olmasının iyi sebepleri vardır. –