2011-06-19 14 views
40

Robię program, który zbliża PI i próbuję używać długo, ale to nie działa. Oto kodJak długo printf długo

#include<stdio.h> 
#include<math.h> 
typedef long long num; 
main(){ 
    num pi; 
    pi=0; 
    num e, n; 
    scanf("%d", &n); 
    for(e=0; 1;e++){ 
     pi += ((pow((-1.0),e))/(2.0*e+1.0)); 
     if(e%n==0) 
     printf("%15lld -> %1.16lld\n",e, 4*pi); 
     //printf("%lld\n",4*pi); 
    } 
} 
+1

Zgaduję, twój problem jest bardziej z 'scanf' niż' printf'. – Nemo

+0

'pow ((- 1.0), e)' byłoby znacznie lepiej wyrażone jako 'e% 2? 1: -1' –

Odpowiedz

-1

Przede wszystkim,% d jest dla int

So %1.16lld nie ma sensu, ponieważ% d jest liczbą całkowitą

To typedef robisz, jest niepotrzebny , używaj tego typu na wprost, tworzy znacznie czytelniejszy kod.

Co chcesz użyć jest rodzaj double, do obliczenia pi a następnie za pomocą %f lub %1.16f.

+0

To naprawdę nie jest "nielegalne" ... myślę, że jest to specyficzne dla MSVC. – Mehrdad

+2

@Mehrdad Od kiedy liczby całkowite mają dziesiętne punkty? –

+6

Niepoprawnie. Przeczytaj [specyfikacja dla printf] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html). '% lld' jest dokładnie tym, jak wydrukujesz' long long'. (Oczywiście, '1.16' może nie robić tego, co chcesz ... Ale jest całkowicie poprawne.Oznacza to użycie minimalnej szerokości pola równej 1 i wydrukowanie 16 cyfr.) – Nemo

53

%lld to standardowy sposób C99, ale to nie działa na używanym kompilatorze (mingw32-gcc v4.6.0). Sposób, w jaki to zrobić na tym kompilator jest: %I64d

Więc spróbuj tego:

if(e%n==0)printf("%15I64d -> %1.16I64d\n",e, 4*pi); 

i

scanf("%I64d", &n); 

Jedynym sposobem wiem za robienie tego w sposób całkowicie przenośny sposób jest użyj definicji w <inttypes.h>.

W twoim przypadku, to będzie wyglądać następująco:

scanf("%"SCNd64"", &n); 
//...  
if(e%n==0)printf("%15"PRId64" -> %1.16"PRId64"\n",e, 4*pi); 

To naprawdę jest bardzo brzydki ... ale przynajmniej jest przenośny.

+7

To nie Twój kompilator, ale biblioteka C, która jest tutaj odpowiedzialna. Używasz biblioteki Microsoft C, która nie obsługuje '% lld', która jest funkcją C99 (chociaż tak samo jest z' inttypes.h'). – caf

+0

Mówiąc dokładniej, jest to msvcrt.dll, która jest starą (około 1998) wersją biblioteki standardowej C, która pierwotnie została napisana dla VC++ 6.0, i jest dostarczana z systemem Windows w celu zapewnienia kompatybilności wstecznej. MinGW używa tej starszej wersji, ponieważ jest to jedyna, która wychodzi z pudełka z systemem Windows. Ale nowoczesne środowisko wykonawcze VC++ obsługuje '% lld' poprawnie. –

+0

Program Visual C++ 2013 wydaje się obsługiwać element formatu% lld – user1741137

2
  • Twoja instrukcja scanf() musi również używać %lld.
  • Twoja pętla nie ma warunku zakończenia.
  • Istnieje zbyt wiele nawiasów i zbyt mało miejsca w wyrażeniu

    pi += pow(-1.0, e)/(2.0*e + 1.0); 
    
  • dodać jedną na pierwszej iteracji pętli, a następnie zera do wartości „pi”; to nie zmienia zbyt dużej wartości.
  • Należy użyć jawnego typu zwrotu: int dla main().
  • Podsumowując, najlepiej jest podać int main(void), gdy ignoruje się jego argumenty, chociaż jest to mniej kategoryczne stwierdzenie niż pozostałe.
  • Nie podoba mi się jawna licencja udzielona w C99, aby pominąć powrót od końca main() i nie używać go samodzielnie; Piszę return 0;, aby było wyraźne.

Myślę, że cały algorytm jest wątpliwy, gdy napisany przy użyciu long long; Typ danych prawdopodobnie powinien być bardziej podobny do long double (z %Lf dla formatu scanf() i może być %19.16Lf dla formatów .

0
double pi = 2 * acos(0.0); 
    int n; 
    scanf("%d",&n); //precision with which you want the value of pi 
    printf("%.*lf\n",n,pi); 
+1

Ten fragment kodu może być rozwiązaniem, ale objaśnienie naprawdę pomaga poprawić jakość wpisu. Pamiętaj, że odpowiadasz na pytanie przeznaczone dla czytelników w przyszłości, a te osoby mogą nie znać powodów sugestii dotyczących kodu –