%s 是允许 printf 正确显示大整数的唯一格式吗?

Is %s the only format that will allow printf to display big integers correctly?

我刚刚花了很长时间才发现我的大整数没问题,而 printf%d/%u 无法完成显示它的任务:

use strict;
use warnings;
use bigint;
use List::Gen;

*factorial = do {use bigint; <[..*] 1, 1..>->code};

my $value = factorial(32);
printf "%d\n", $value;  # -1
printf "%u\n", $value;  # 18446744073709551615
printf "%s\n", $value;  # 263130836933693530167218012160000000

如果答案是否定的,我不会感到惊讶,只是想确认一下。

这出乎意料地难以追踪。我没有在文档中看到任何明显的内容,所以我去了源代码。 printf 函数由 C 函数 Perl_sv_vcatpvfn_flags 实现(在长调用堆栈的底部)。看起来好像这个函数假设数字适合 IV 或 UV。它们由

定义
typedef IVTYPE IV;
typedef UVTYPE UV;

依次定义(至少在我的 Perl 上,我认为这是可配置的)

#define IVTYPE          long            /**/
#define UVTYPE          unsigned long           /**/

因此,如果您的数字不适合长整型 (%d) 或无符号长整型 (%u),则字符串 (%s) 是你唯一的选择。一个更大的问题是你为什么首先使用 printf 。除了打印它们之外,您是否以某种方式格式化这些数字?如果不是,那么 print 应该做正确的事。

是的。 %s 是字符串的唯一格式。


  • %%:显然不是。
  • %c:显然不是。
  • %s:是的。
  • %d:仅当数字适合有符号整数时。
  • %u%o%x%X%b%B:仅当数字适合无符号整数时.
  • %e%E%f%g%G%a%A:仅当数字适合浮点数。
  • %p:显然不是。
  • %n:显然不是。

鉴于您必须使用特定的库来处理这些数字,因此没有理由期望 builtin printf 会处理它们。相反,您可以使用库的 conversion functions,例如 as_hexbnstr。如果您只想打印数字,请使用 print "$value\n";.