2012-05-04 7 views
1

私はCppを使用して階乗でゼロの数を見つけたいと思っています。問題は私が本当に大きな数字を使うときです。実際に長い数字(fmod)のモジュラス

#include <stdio.h> 
#include <math.h> 

long zeroesInFact(long n) 
{ 
long double fact=1; 
long double denominator=10.00; 
long double zero=0.0000; 
long z=0; 
printf("Strating loop with n %ld\n",n); 
for(int i=2;i<=n;i++) 
{ 
    fact=fact*i; 
    printf("Looping with fact %LF\n",fact); 
} 
printf("Fmod %lf %d\n",fmod(fact,denominator),(fmod(fact,denominator)==zero)); 
while(fmod(fact,denominator)==zero) 
{ 
    fact=fact/10; 
    z++; 
} 
printf("Number of zeroes is %ld\n",z); 
return z; 
} 

int main() 
{ 
long n; 
long x; 
scanf("%ld",&n); 
for(int i=0;i<n;i++) 
{ 
    scanf("%ld",&x); 
    printf("Calling func\n"); 
    zeroesInFact(x); 
} 
return 0; 
} 

は、私がここでの問題は

FMOD(実際、分母) は(0.000である)10.00として私の22の階乗と分母のために正しい答えを与えることだと思います。 しかし、23の階乗と分母に間違った答えを与えます10.00

+2

ヒント:製品内のゼロの数は、被乗数の素因数のリストにある「5」および「2」の数に関連しています。 –

+1

全くありません。 11^5 = 161051. OPが彼が述べたように「0の数」に関心があるのか​​、あるいは「0のTRAILING数」を本当に望んでいるのかは明確ではない。彼のコードから、彼は2番目を望むように見えます。 – fjardon

+0

おそらく[この関連の議論](http://stackoverflow.com/q/2847069/312172)は面白いです。 –

答えて

3

これは最初のレッスンを数値精度で考えてみてください。 floatdouble、およびlong doubleは、正確な値ではなく、近似値を格納します。つまり、通常、このような計算には不適切です。彼らが正解に十分な精度を持っていても、代わりにint64_tuint64_tのように整数数値型を使用する方が良いでしょう。場合によっては、128ビットの整数型も使用できます。 (例:__int128はMicrosoft Visual Studioで利用可能かもしれません)

正直言って、18!から22!の正解を得ることは幸運だったと思います。

long doubleが本当にあなたのプラットフォームで4倍精度である場合は、30!まで計算できるはずです。 fmodを使用したときにあなたが間違っていた - fmodlを使用したことがあります。


精度の2番目のレッスンは、多くの場合、基本的なデータタイプでは十分ではないということです。独自のデータ型を記述することはできますが、既存のソリューションを使用する方がよいでしょう。 Gnu Multiple Precision算術ライブラリ(GMP)は、C/C++で使用できる優れた高速ライブラリです。

また、言語を切り替えることもできます(例: python整数データ型は任意の精度ですが(GMPほど高速ではありません)、特別な処理は必要ありません。 Javaはそのような計算を行うためにBigIntegerクラスを持っています。


あなたの3番目のレッスンは、精度がなくてはならない方法を見つけることです。実際に23!を計算して末尾のゼロの数を見つける必要はありません。注意して、必要のない精度を捨てるように計算を整理することができます。あるいは、あなたは、Robが彼のコメントで示唆していたものなど、この数字を得る全く異なる方法に切り替えることができます。

+0

レッスンは十分に学習されました。ありがとう:)私はちょうど階乗で5の数が必要であることに気付いた –

関連する問題