Как я могу спринт большого числа в Perl? - PullRequest
3 голосов
/ 06 мая 2009

На 32-битной платформе Windows я должен прочитать некоторые цифры, которые, как это ни было неожиданно, могут иметь значения до 99 999 999 999, но не более. При попытке sprintf("%011d", $myNum) их выводит переполнение: -2147483648.

Я не могу использовать модуль BigInt, потому что в этом случае я должен глубоко изменить код. Я не могу управлять форматом как строка, sprintf("%011s", $numero), потому что знак минус неправильно обрабатывается.

Как мне это сделать? Может ли упаковать / распаковать какую-нибудь помощь?

Ответы [ 4 ]

11 голосов
/ 06 мая 2009

Попробуйте отформатировать его как число с плавающей точкой без дробной части:

$ perl -v
This is perl, v5.6.1 built for sun4-solaris
...

$ perl -e 'printf "%011d\n", 99999999999'
-0000000001

$ perl -e 'printf "%011.0f\n", 99999999999'
99999999999
1 голос
/ 06 мая 2009

Да, одно из числовых мертвых зон Perl - форматирование; Perl автоматически обрабатывает представление чисел в виде целых чисел или с плавающей точкой, но затем приводит их к один или другой, когда используются числовые форматы printf, даже если это не так подходящее. И printf на самом деле вообще не справляется с BigInts (за исключением лечения их в виде строк и преобразования их в число с потерей точности).

Использование% s вместо% d с любым числом, которое вы не уверены, будет в соответствующем Диапазон - хороший обходной путь, за исключением того, что вы заметили отрицательные числа. Обрабатывать те, вам придется написать некоторый код Perl.

0 голосов
/ 06 мая 2009

Я думаю, что ваша копия Perl должна быть сломана, это из версии CygWin (5.10):

pax$ perl -e 'printf("%011d\n", 99999999999);'
99999999999

pax$ perl -v

This is perl, v5.10.0 built for cygwin-thread-multi-64int
(with 6 registered patches, see perl -V for more detail)

Copyright 1987-2007, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Какую версию вы используете (вывод perl -v)?

Возможно, вам придется получить 64-битную версию Perl [и, возможно, новую 64-битную рабочую машину] (обратите внимание на "cygwin-thread-multi-64int" в моем выводе). Это, по крайней мере, позволит избежать необходимости изменения кода.

Я утверждаю это на том основании, что вы не хотите сильно менять код (то есть боитесь что-то сломать). Решение нового оборудования, хотя и немного дорогое, почти наверняка не потребует от вас изменения программного обеспечения на всех . Это зависит от ваших приоритетов.

Другая возможность состоит в том, что сам Perl может правильно хранить число, но просто отображать его неправильно из-за ошибки printf(). В этом случае вы можете попробовать:

$million = 1000000;
$bignum = 99999999999;
$firstbit = int($bignum / $million);
$secondbit = $bignum - $firstbit * million;
printf ("%d%06d\n",$firstbit,$secondbit);

Поместите это в функцию и вызовите функцию, чтобы вернуть строку, например:

sub big_honkin_number($) {
    $million = 1_000_000;
    $bignum = shift;
    $firstbit = int($bignum / $million);
    $secondbit = $bignum - $firstbit * $million;
    return sprintf("%d%06d\n", $firstbit, $secondbit);
}
printf ("%s", big_honkin_number (99_999_999_999));

Обратите внимание, что я тестировал это, но на 64-битной платформе - вам нужно будет провести свой собственный тест на 32-битной платформе, но вы можете использовать любой масштабный коэффициент, который вы хотите (включая более двух сегментов, если это необходимо). 1021 *

Обновление: Этот трюк big_honkin_number() отлично работает на 32-битном Perl, так что похоже, что это только функции printf(), которые наполняют вас: *

pax@pax-desktop:~$ perl -v

This is perl, v5.8.8 built for i486-linux-gnu-thread-multi

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

pax@pax-desktop:~$ perl qq.pl
99999999999
0 голосов
/ 06 мая 2009

Я не эксперт по Perl, и, возможно, мне здесь не хватает какой-то автоматической обработки бигнумов, но разве это не просто случай целочисленного переполнения? 32-разрядное целое число не может содержать числа размером более 99 999 999 999.

В любом случае, я получаю тот же результат с Perl v5.8.8 на моей 32-битной Linux-машине, и кажется, что printf с "% d" не обрабатывает большие числа.

...