Является ли %s единственным форматом, который позволит printf корректно отображать большие целые числа?

#perl #printf #biginteger

#perl #printf #biginteger

Вопрос:

Я только что потратил целую эпоху, выясняя, что с моим большим целым числом все в порядке, и что printf «s %d / %u не справились с задачей его отображения:

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

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

my $value = factorial(32);
printf "%dn", $value;  # -1
printf "%un", $value;  # 18446744073709551615
printf "%sn", $value;  # 263130836933693530167218012160000000
  

Я не удивлюсь, если ответ будет отрицательным, просто хотел подтвердить это.

Ответ №1:

Это было на удивление сложно отследить. Я не увидел ничего очевидного в документах, поэтому я пошел к источнику. printf Функция реализована (в нижней части длинного стека вызовов) функцией C. Perl_sv_vcatpvfn_flags Похоже, что эта функция предполагает, что число поместится в IV или UV. Они определяются

 typedef IVTYPE IV;
typedef UVTYPE UV;
  

Который, в свою очередь, определяется (по крайней мере, на моем Perl, я думаю, это настраивается)

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

Итак, если ваше число не помещается в long , then ( %d ) или в unsigned long ( %u ) , тогда string ( %s ) — ваш единственный вариант. Больший вопрос заключается в том, почему вы используете printf в первую очередь. Вы форматируете эти числа каким-либо другим способом, кроме их печати? Если нет, то print следует просто поступить правильно.

Комментарии:

1. Не было никакой особой причины использовать printf , кроме того факта, что он уже был там, когда я начал вводить в свой процесс огромные числа.

Ответ №2:

ДА. %s это единственный формат для строк.


  • %% : Очевидно, нет.
  • %c : Очевидно, нет.
  • %s : Да.
  • %d : Только если число вписывается в целое число со знаком.
  • %u , %o , %x , %X , %b , %B : Только если число помещается в целое число без знака.
  • %e , %E , %f , %g , %G , %a , %A : Только если число вписывается в число с плавающей запятой.
  • %p : Очевидно, нет.
  • %n : Очевидно, нет.

Ответ №3:

Учитывая, что вы должны использовать определенную библиотеку для манипулирования такими числами, нет никаких оснований ожидать, что встроенная printf программа их обработает. Вместо этого вы можете использовать функции преобразования библиотеки, такие как as_hex или bnstr . Если вы просто хотите напечатать число, используйте print "$valuen"; .

Комментарии:

1. Прагма bigint является частью ядра Perl 5, я понимаю, почему (без дополнительной документации) вы можете ожидать, что Perl 5 правильно ее обработает.