2008-11-04 7 views

Odpowiedz

5

Parsować liczbę do postaci a + N/(10^k), gdzie a i N są liczbami całkowitymi, a k to liczba miejsc dziesiętnych, które posiadasz.

przykład: 12,0345 -> 12 + 345/10^4, a = 12, N = 345, K = 4

Teraz 10^K = (2 * 5)^k = 2^k * 5^k

Możesz podać swój numer jako dokładną frakcję binarną wtedy i tylko wtedy, gdy pozbędziesz się 5^k terminu w mianowniku.

Efektem byłoby sprawdzić (N^K mod 5) == 0

+0

co z 11111111111111111111111111111111111111111111111111111111111111111? – BCS

+0

Lub lepszy sposób na umieszczenie go (100/epsilon + 1) – BCS

-2

przekonwertować ciąg do pływaka z większym zakresie niż podwójne. Rzuć to do podwójnego i sprawdź, czy pasują.

+0

Byłoby miło wiedzieć, dlaczego ta została przegłosowana. Jeśli moja odpowiedź jest błędna, proszę powiedz mi dlaczego. – Treb

+0

długi podwójny == podwójny w niektórych systemach – BCS

+0

Wszystko bardzo dobrze, ale może nie być takiego pływaka. – DJClayworth

0

To powinno załatwić sprawę:

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

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

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

Prawdopodobnie najlepiej użyć „bezpieczne” wersję sprintf aby zapobiec potencjalnej przepełnienie bufora

+0

To nie działa, jeśli liczba ma precyzję inną niż 6 (domyślna precyzja formatu% lf) –

+0

Można dynamicznie ustawić ciąg "% f", aby uzyskać właściwa szerokość. Aby być w pełni niezawodnym, musisz zająć się białymi znakami, prowadzącymi, a nie zerami, +, - i innymi specjalnymi przypadkami. –

+0

snprintf byłby "bezpieczną" wersją - http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/printf.htm –

0

I”(jest to w ogóle możliwe w tym przypadku?) d przekonwertuj ciąg znaków na jego numeryczną reprezentację bitową (bitową lub długą), a następnie przekonwertuj ciąg znaków na podwójne i sprawdź, czy pasują do siebie.

+0

.. i co jeśli (na twoim komputerze) długi podwójny jest tego samego rozmiaru co podwójny? – DJClayworth

+0

Przepraszamy, wysłałem ten komentarz do niewłaściwej odpowiedzi. – DJClayworth

1

Oto moja wersja. sprintf konwertuje 0.5 na 0.50000, zera na końcu muszą zostać usunięte.

EDYCJA: Musi być przepisany, aby obsługiwać liczby bez przecinka dziesiętnego, które kończą się z 0 poprawnie (jak 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

Prawie - a co z 1.200e10? – DJClayworth

5

Święte zadanie domowe, batman! :)

Co sprawia, że ​​jest to interesujące, że nie można po prostu zrobić (atof | strtod | sscanf) -> sprintf loop i sprawdzić, czy masz oryginalny ciąg z powrotem. sprintf na wielu platformach wykrywa "tak blisko, jak to możliwe, że osiąga 0,1" i drukuje na przykład jako 0,1, chociaż 0.1 nie jest dokładnie reprezentowalny.

#include <stdio.h> 

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

drukuje: 3fb999999999999a = 0,100000

w moim systemie.

Prawdziwa odpowiedź prawdopodobnie wymagałoby parsowania się podwójnie, aby przekształcić go do dokładnej reprezentacji ułamkowej (0,1 = 1/10), a następnie upewnić się, że czasy konwersji atof mianownik równa liczniku.

Myślę.

Powiązane problemy