2016-07-11 11 views
0

Ich schreibe eine Funktion, in der ich faktorielle Zahlen berechnen und Operationen an ihnen ausführen muss. Der Rückgabewert der Funktion sollte lang sein, also denke ich, es wäre besser, alle Operationen auszuführen im langen langen Format. Wenn ich falsch liege, korrigiere mich bitte.tgamma() lang lang typecasting

Die Funktion tgamma() liefert selbst den korrekten Wert in wissenschaftlicher Schreibweise. Aber der von tgamma() zurückgegebene Wert ist manchmal 1 weniger als die tatsächliche Antwort, wenn der von der Funktion zurückgegebene Wert in 'lang lang' eingegeben wird.

int main() 
{ 
std::cout<<"11!:"<<tgamma(12)<<std::endl; 
std::cout<<"12!"<<tgamma(13)<<std::endl; 
std::cout<<"13!"<<tgamma(14)<<std::endl; 
std::cout<<"14!"<<tgamma(15)<<std::endl; 
std::cout<<"15!"<<tgamma(16)<<std::endl; 
std::cout<<"16!"<<tgamma(17)<<std::endl; 
std::cout<<"********************************"<<std::endl; 
std::cout<<"11!:"<<(long long)tgamma(12)<<std::endl; 
std::cout<<"12!"<<(long long)tgamma(13)<<std::endl; 
std::cout<<"13!"<<(long long)tgamma(14)<<std::endl; 
std::cout<<"14!"<<(long long)tgamma(15)<<std::endl; 
std::cout<<"15!"<<(long long)tgamma(16)<<std::endl; 
std::cout<<"16!"<<(long long)tgamma(17)<<std::endl; 
return 0; 
} 

ich die folgende Ausgabe bin immer:

11!:3.99168e+07 
12!4.79002e+08 
13!6.22702e+09 
14!8.71783e+10 
15!1.30767e+12 
16!2.09228e+13 
******************************** 
11!:39916800 
12!479001599 
13!6227020799 
14!87178291199 
15!1307674367999 
16!20922789888000 

Der tatsächliche Wert von 15! nach this site ist 1307674368000 aber wenn ich tgamma (16) zu lang lang tippen, bekomme ich nur 1307674367999. Die Sache ist diese Diskrepanz erscheint nur für einige Zahlen. Die eingegebene Antwort für 16! ist korrekt - 20922789888000.

Diese Funktion ist für ein konkurrierendes Programmierproblem, das gerade läuft, so dass ich die Funktion und die Lösung, die ich hier entwickle, nicht einfügen kann.

Ich würde meine eigene faktorielle Funktion rollen, aber ich möchte die Anzahl der Zeichen in meinem Programm reduzieren, um Bonuspunkte zu erhalten.

Gibt es Tipps, wie Sie diese Diskrepanz im eingegebenen Wert erkennen und korrigieren können? Oder vielleicht eine andere Funktion, die ich verwenden kann?

+0

tgamma arbeitet mit Fließkommazahlen, die ihre Genauigkeit verlieren können. Warum schreibst du nicht einfach deine eigene faktorielle Funktion mit ganzen Zahlen? – jtbandes

+0

"Die Funktion tgamma() liefert selbst den korrekten Wert in wissenschaftlicher Schreibweise." - Nein, tut es nicht. C++ hat ein sauberes Design. Der Wert wird als Binärwert zurückgegeben. Wissenschaftliche Notation ist ein Textformat, das beim Konvertieren eines Binärwerts in Text angewendet werden kann. – MSalters

Antwort

0

Umwandlung von einem Fließkommatyp in einen Integraltyp wird abgeschnitten. Versuchen Sie (long long) roundl(tgammal(xxx)), um den ganzzahligen Kürzungsfehler loszuwerden. Dies verwendet auch lange Doppel, so dass es Ihnen mehr Ziffern geben kann.

#include <math.h> 
#include <iostream> 
int main(){ 
    std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl; 
    std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl; 
    std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl; 
    std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl; 
    std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl; 
    std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl; 
    std::cout<<"********************************"<<std::endl; 
    std::cout<<"11!:"<<(long long)roundl(tgammal(12))<<std::endl; 
    std::cout<<"12!"<<(long long)roundl(tgammal(13))<<std::endl; 
    std::cout<<"13!"<<(long long)roundl(tgammal(14))<<std::endl; 
    std::cout<<"14!"<<(long long)roundl(tgammal(15))<<std::endl; 
    std::cout<<"15!"<<(long long)roundl(tgammal(16))<<std::endl; 
    std::cout<<"16!"<<(long long)roundl(tgammal(17))<<std::endl; 
    return 0; 
} 

Gibt:

11!:39916800 
12!479001600 
13!6227020800 
14!87178291200 
15!1307674368000 
16!20922789888000 
******************************** 
11!:39916800 
12!479001600 
13!6227020800 
14!87178291200 
15!1307674368000 
16!20922789888000 
+0

das hat mir geholfen. Danke! –

+0

Warum erscheint dieser Fehler nur für einige Zahlen? Sollte es nicht einheitlich sein, wenn es ein Fehler ist? Warum nur 15! typecasted Antwort ist falsch, während 16! Antwort ist nicht? –

+1

Tgamma ist ungefähr. Casting zu einem integralen Typ schneidet statt Runden Runden ab. Die Verwendung von mehr Ziffern und Runden/Runden hilft bei beiden. – evaitl

0

Offensichtlich, es sei denn wir sehr ungewöhnliche Umsetzung haben, nicht alle lange lange Zahlen können genau wie doppelt dargestellt werden. Daher kann tgamma keine doppelten Werte speichern, so dass das Gießen zu lange lange einen genauen Wert ergeben würde. Es gibt einfach mehr lange lange Werte als doppelte Werte innerhalb eines langen langen Intervalls.

Wenn Sie genau lange lange Fakultät wollen, sollten Sie es selbst implementieren.

Obendrein, wenn Sie Präzision wünschen, transformieren Sie doppelt in lang lang nicht als (lang lang) x, sondern als (lang lang) rund (x) oder (lang lang) (x + 0,5), Angenommen, x ist positiv.

+0

nette Erklärung! Die (lange lange) (tgamma (x) + 0,5) produziert kürzere Code ... netter Tipp! –

+0

Gibt es eine Standard-C++ - Funktion, die die genaue Fakultät einer Zahl zurückgibt, ohne solche Umgehungsfehler-Problemumgehungen zu machen? –

+0

Google für 'std factorial standard library' und Sie werden die Antwort finden :) – user31264