如何printf long long

60

我正在编写一个近似PI的程序,尝试使用long long,但它不起作用。这是代码:

#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
我猜你的问题更多是与 scanf 有关,而不是 printf - Nemo
pow((-1.0),e) would be much better expressed as e % 2 ? 1 : -1 - phuclv
4个回答

76

%lld 是标准的C99写法,但在我使用的编译器(mingw32-gcc v4.6.0)上无法正常工作。在这个编译器上的写法是:%I64d

因此,请尝试这样写:

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

scanf("%I64d", &n);

我所知道的完全可移植的方法,是使用<inttypes.h>中的宏定义。

在您的情况下,它应该像这样:

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

它真的很丑...但至少它是可移植的。


11
这里的责任并非在于你的编译器,而是在于你使用的 C 库。你正在使用微软的 C 库,它不支持 %lld,这是一个 C99 特性(尽管 inttypes.h 也是)。 - caf
1
更具体地说,它是msvcrt.dll,这是最初为VC++ 6.0编写的古老(约1998年左右)版本的C标准库,并随Windows一起提供以实现向后兼容性。MinGW使用这个古老的版本,因为它是与Windows捆绑在一起的唯一版本。但是,现代的VC++运行时会正确处理%lld - Pavel Minaev
1
Visual C++ 2013似乎支持%lld格式元素。 - user1741137
1
@PavelMinaev,随Windows捆绑的msvcrt.dll并不古老。 - Pavel P
它已经被修补了,但自VC++ 6.0以来,我没有听说过其实际功能的任何更新。 - Pavel Minaev
使用新的WSL的好处之一是,您可以使用更新的GCC或CLANG处于编写C语言的现代状态。比MINGW更兼容。 - Brian Bulkowski

3
  • Your scanf() statement needs to use %lld too.
  • Your loop does not have a terminating condition.
  • There are far too many parentheses and far too few spaces in the expression

    pi += pow(-1.0, e) / (2.0*e + 1.0);
    
  • You add one on the first iteration of the loop, and thereafter zero to the value of 'pi'; this does not change the value much.
  • You should use an explicit return type of int for main().
  • On the whole, it is best to specify int main(void) when it ignores its arguments, though that is less of a categorical statement than the rest.
  • I dislike the explicit licence granted in C99 to omit the return from the end of main() and don't use it myself; I write return 0; to be explicit.

我认为使用long long编写的整个算法是可疑的;数据类型可能更像long double(使用%Lf作为scanf()格式,也许使用%19.16Lf作为printf()格式)。


0
首先,%d 是一个 int 的占位符。
所以 %1.16lld 没有意义,因为 %d 是整数的占位符。
你声明的那个 typedef 也是不必要的,直接使用类型会使代码更易读。
你想要使用的类型是 double,用于计算 pi,然后使用 %f%1.16f

这并不是真正的“非法”的……我认为这是MSVC特定的。 - user541686
7
不正确。请阅读printf规范%lld正是打印long long的方法。(当然,1.16可能不会达到你的预期...但这是完全有效的。它表示使用最小字段宽度为1并打印16个数字。) - Nemo
@Mehrdad 你指的是 %lld 吗?它在 C99 7.19.6.1 中有规定。 - Pascal Cuoq
@Pascal:哦,我不知道,那就更好了。 @hexa:抱歉,我是在提到lld,而不是小数点……我以为你是指那个,我的错。 - user541686
1
MSVC使用%I64d%lld等格式来表示64位的long long格式。 - Jonathan Leffler

0
    // acos(0.0) will return value of pi/2, inverse of cos(0) is pi/2 
    double pi = 2 * acos(0.0);
    int n; // upto 6 digit
    scanf("%d",&n); //precision with which you want the value of pi
    printf("%.*lf\n",n,pi); // * will get replaced by n which is the required precision

2
虽然这段代码片段可能是解决方案,但包括解释真的有助于提高您的帖子质量。请记住,您正在回答未来读者的问题,而这些人可能不知道您提出代码建议的原因。 - Rahul Gupta
虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - double-beep
好的,我会添加更多细节 @double-beep - Atul Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接