2008-11-04 11 views

Antwort

5

Analysieren Sie die Zahl in die Form a + N/(10^k), wobei a und N ganze Zahlen sind und k die Anzahl der Dezimalstellen ist, die Sie haben.

Beispiel: 12,0345 -> 12 + 345/10^4, a = 12, N = 345, k = 4

nun 10^k = (2 * 5)^k = 2^k * 5^k

Sie können Ihre Zahl als genaues binäres Bruchstück darstellen, wenn und nur wenn Sie den 5^k Ausdruck im Nenner loswerden.

Das Ergebnis würde überprüfen (N mod 5^k) == 0

+0

was ist mit 11111111111111111111111111111111111111111111111111111111111111111? – BCS

+0

Oder ein besserer Weg (100/Epsilon + 1) – BCS

-2

Konvertieren der Zeichenfolge in einen Schwimmer mit einem größeren Umfang als ein Doppelzimmer. Wirf das auf ein Double und schau, ob sie übereinstimmen.

+0

Wäre schön zu wissen, warum dies abgelehnt wurde. Wenn meine Antwort falsch ist, bitte sag mir warum. – Treb

+0

lang doppelt == doppelt auf einigen Systemen – BCS

+0

Alles sehr gut, aber es kann nicht so ein Schwimmer sein. – DJClayworth

0

Diese den Trick tun soll:

bool isRepresentable(const char *realNumber) 
{ 
    double value = strtod(realNumber, NULL); 

    char test[20]; 
    sprintf(test, "%f", value); 

    return strcmp(realNumber, test) == 0; 
} 

Wahrscheinlich am besten verwenden, um die 'sichere' Version von sprintf einen potenziellen Pufferüberlauf zu verhindern

+0

Das funktioniert nicht, wenn die Zahl eine andere Genauigkeit als 6 (die Standardpräzision des% lf-Formats) hat –

+0

Sie könnten die "% f" Zeichenfolge dynamisch festlegen richtige Breite. Sie müssen mit Leerraum umgehen, mit führenden und nicht Nullen, +, - und anderen Sonderfällen, um vollständig robust zu sein. –

+0

snprintf wäre eine "sichere" Version - http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/printf.htm –

0

I‘(ist es sogar möglich, in diesem Fall?) d wandeln Sie die Zeichenfolge in ihre numerische Bit-Darstellung um (ein Bit-Array oder ein Long-Bit), konvertieren Sie dann die Zeichenfolge in ein Double, und prüfen Sie, ob sie übereinstimmen.

+0

..und was ist, wenn (auf Ihrer Maschine) lang doppelt so groß ist wie doppelt? – DJClayworth

+0

Entschuldigung, ich habe diesen Kommentar auf die falsche Antwort gepostet. – DJClayworth

1

Hier ist meine Version. sprintf konvertiert 0,5 bis 0,50000, am Ende müssen Nullen entfernt werden.

EDIT: Muss neu geschrieben werden, um Zahlen ohne Dezimalpunkt zu behandeln, die mit 0 korrekt enden (wie 12300).

 
bool isRepresentable(const char* realNumber) 
{ 
    bool answer = false; 

    double dVar = atof(realNumber); 
    char check[20]; 
    sprintf(check, "%f", dVar); 

    // Remove zeros at end - TODO: Only do if decimal point in string 
    for (int i = strlen(check) - 1; i >= 0; i--) { 
    if (check[i] != '0') break; 
    check[i] = 0; 
    } 

    answer = (strcmp(realNumber, check) == 0); 

    return answer; 
} 
+0

Fast - was ist mit 1.200e10? – DJClayworth

5

Heilige Hausaufgaben, Batman! :)

Was das interessant macht ist, dass Sie nicht einfach eine (atof | strtod | sscanf) -> sprintf Schleife machen und überprüfen können, ob Sie die ursprüngliche Zeichenfolge zurückbekommen haben. Sprintf auf vielen Plattformen erkennt das "so nah wie möglich an 0.1" Double und druckt es beispielsweise als 0.1, obwohl 0.1 nicht genau darstellbar ist.

#include <stdio.h> 

int main() { 
    printf("%llx = %f\n",0.1,0.1); 
} 

druckt: 3fb999999999999a = 0.100000

auf meinem System.

Die echte Antwort würde wahrscheinlich erfordern, das Doppelte zu analysieren, um es in eine exakte Bruchteildarstellung (0.1 = 1/10) zu konvertieren und dann sicherzustellen, dass die atof Umwandlung mal der Nenner dem Zähler entspricht.

Ich denke.

Verwandte Themen