разница в printf между c и perl - PullRequest
2 голосов
/ 26 июня 2019

В C:

printf ("%u", 17860374324089702869);

печатает "3336554965" (это ответ, который я хочу!)

В perl, та же строка кода печатает "17860374324089702869".

Как я могу заставить Perl выдавать "3336554965" из "17860374324089702869".

Мой инстинкт говорит, что это проблема 64-битных и 32-битных, но не похоже, что оператор perl что-то делаетна все номера.

Ответы [ 4 ]

5 голосов
/ 26 июня 2019

В С printf %u занимает unsigned int. Является ли это 32-битным или 64-битным значением или чем-то другим, полностью зависит от вашей реализации C Стандарт требует, чтобы ширина int была не менее 16 бит. (Поскольку значение, которое вы передаете в своем примере, не помещается в unsigned int, я почти уверен, что ваш код имеет неопределенное поведение: вы не передаете unsigned int в %u, как ожидается .)

В Perl %u преобразует свой аргумент в целое число без знака. Ширина этого целого числа зависит от того, как Perl был скомпилирован; обычно это 32-битный или 64-битный тип. Вы можете запросить информацию о конфигурации вашего perl, запустив perl -V:uvsize (размер целого типа без знака в байтах Perl) и perl -V:uvtype (соответствующий тип C).

Если вы хотите явно урезать свое значение до 32 бит, возможно, самый простой способ - применить битовую маску:

use constant { UINT32_MAX => 0xffff_ffff };
print 17860374324089702869 & UINT32_MAX, "\n";

Тогда вам действительно не нужно printf.

1 голос
/ 26 июня 2019

В Perl нет такого 32-битного целого без знака.17860374324089702869 становится 3336554965 в C, потому что 32-разрядное целое число без знака имеет диапазон от 0 до 4294967295, когда происходит переполнение, целое число поднимается из нижней границы и наоборот

например

unsigned int a = 4294967296 // will be 0 because unsigned integer upper limit is 4294967295

Так что вам нужно только модулировать его с 4294967296, потому что есть 4294967296 номеров от 0 до 4294967295

#!/usr/bin/perl

printf "%09u", 17860374324089702869 % 4294967296
0 голосов
/ 26 июня 2019

Язык C имеет множество числовых типов данных (и размеров). Perl имеет 3 типа данных - « скаляры, массивы скаляров и ассоциативные массивы скаляров »,

В Perl скалярные значения являются полиморфными, поэтому значение 17860374324089702869 можно рассматривать как строку или число, в зависимости от того, как оно используется. При использовании в выражении printf он обрабатывается как номер 17860374324089702869 и печатается как таковой.

В C целое число без знака обрабатывается как целое число в диапазоне, определяемом размером слова в архитектуре, для которой вы компилируете программу. Вы должны были получить предупреждение при компиляции. Когда я скомпилировал вышеупомянутое утверждение с -Wall, вот предупреждение, которое я получил:

предупреждение: формат «% u» ожидает аргумент типа «unsigned int», но аргумент 2 имеет тип «__int128» [-Wformat =]

В этом посте обсуждается максимальное целочисленное значение, на которое можно рассчитывать в Perl.

0 голосов
/ 26 июня 2019

Обычно речь идет не о printf / sprintf в Perl, а о том, как Perl хранит целые числа и передает целые числа в функции. Как упоминалось в других ответах, в Perl нет 32-разрядного целочисленного типа.

По сути, вам нужно вырезать половину вашего 64-битного целого числа, чтобы сделать его 32-битным. Для этого просто используйте двоичный файл &:

perl -e 'printf("%09u\n", 17860374324089702869 & 0xffffffff);'
3336554965

Здесь операция & оставляет биты младших 4 байтов неизменными, но устанавливает биты старших 4 байтов в нули.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...