2011-06-19 37 views
40

Tôi đang làm một chương trình mà aproximate PI và tôi đang cố gắng sử dụng lâu dài, nhưng nó không hoạt động. Đây là mãLàm thế nào để printf dài

#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

Tôi đoán vấn đề của bạn là nhiều hơn với 'scanf' so với' printf'. – Nemo

+0

'pow ((- 1.0), e)' sẽ được thể hiện tốt hơn nhiều như 'e% 2? 1: -1' –

Trả lời

-1

Trước hết,% d là một int

Vì vậy %1.16lld làm cho không có ý nghĩa, bởi vì% d là một số nguyên

Đó typedef bạn làm thế, cũng là không cần thiết , sử dụng loại thẳng về phía trước, tạo một mã dễ đọc hơn nhiều.

Điều bạn muốn sử dụng là loại double, để tính pi và sau đó sử dụng %f hoặc %1.16f.

+0

Nó không thực sự "bất hợp pháp" ... đó là đặc trưng của MSVC, tôi nghĩ vậy. – Mehrdad

+2

@Mehrdad Kể từ khi số nguyên có dấu thập phân? –

+6

Không chính xác. Đọc [spec for printf] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html). '% lld' chính xác là cách bạn in một' long long'. (Tất nhiên, '1.16' có thể không làm những gì bạn muốn ... Nhưng nó hoàn toàn hợp lệ. Nó có nghĩa là sử dụng chiều rộng trường tối thiểu là 1 và in 16 chữ số.) – Nemo

53

%lld là cách C99 chuẩn, nhưng điều đó không hoạt động trên trình biên dịch tôi đang sử dụng (mingw32-gcc v4.6.0). Cách để làm điều đó trên trình biên dịch này là: %I64d

Vì vậy, cố gắng này:

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

scanf("%I64d", &n); 

Cách duy nhất tôi biết để làm điều này theo một cách hoàn toàn di động là sử dụng các định nghĩa trong <inttypes.h>.

Trong trường hợp của bạn, nó sẽ trông như thế này:

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

Nó thực sự là rất xấu xí ... nhưng ít nhất nó là xách tay.

+7

Nó không phải là trình biên dịch của bạn mà là thư viện C của bạn chịu trách nhiệm ở đây. Bạn đang sử dụng thư viện Microsoft C, không hỗ trợ '% lld', là một tính năng C99 (mặc dù vậy là' inttypes.h'). – caf

+0

Để cụ thể hơn, đó là msvcrt.dll, là phiên bản cổ (vào khoảng năm 1998) của thư viện chuẩn C vốn được viết cho VC++ 6.0 và được giao với Windows cho mục đích tương thích ngược. MinGW sử dụng phiên bản cũ đó, bởi vì đó là phiên bản duy nhất xuất hiện với Windows. Nhưng thời gian chạy VC++ hiện đại xử lý '% lld' đúng cách. –

+0

Visual C++ 2013 dường như hỗ trợ phần tử định dạng% lld – user1741137

2
  • Tuyên bố scanf() của bạn cũng cần sử dụng %lld.
  • Vòng lặp của bạn không có điều kiện kết thúc.
  • Có quá nhiều dấu ngoặc đơn và quá ít khoảng trống trong biểu thức

    pi += pow(-1.0, e)/(2.0*e + 1.0); 
    
  • Bạn thêm một trên phiên đầu tiên của vòng lặp, và sau đó không để giá trị của 'pi'; điều này không thay đổi giá trị nhiều.
  • Bạn nên sử dụng loại trả lại rõ ràng là int cho main().
  • Nói chung, tốt nhất là chỉ định int main(void) khi bỏ qua các đối số của nó, mặc dù đó là ít hơn một tuyên bố phân loại so với phần còn lại.
  • Tôi không thích giấy phép rõ ràng được cấp trong C99 để bỏ qua sự trở lại từ cuối main() và không sử dụng bản thân; Tôi viết return 0; để rõ ràng.

Tôi nghĩ rằng toàn bộ thuật toán không rõ ràng khi được viết bằng cách sử dụng long long; loại dữ liệu có thể phải giống như long double (với %Lf cho định dạng scanf() và có thể là %19.16Lf cho các định dạng printf().

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

Mặc dù đoạn mã này có thể là giải pháp, bao gồm giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho người đọc trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn –

Các vấn đề liên quan