Мне нужно сделать некоторую арифметику с большими шестнадцатеричными числами ниже, но при попытке вывода я получаю сообщения об ошибках переполнения "Шестнадцатеричное число> 0xffffffff непереносимые", сообщения о непереносимых или максимальных 32-битных шестнадцатеричных числах.значение FFFFFFFF.
Все это подразумевает, что стандартный язык и выходные процедуры работают только с 32-битными значениями.Мне нужны 64-битные значения и я провел много исследований, но я ничего не нашел, чтобы ОБА включила арифметику и вывела большое число в шестнадцатеричном формате.
my $result = 0x00000200A0000000 +
( ( $id & 0xFFFFF ) * 2 ) + ( ( $id / 0x100000 ) * 0x40000000 );
Итак, для $ id со следующими значениями Iдолжен получить $result
:
$id = 0, $result = 0x00000200A0000000
$id = 1, $result = 0x00000200A0000002
$id = 2, $result = 0x00000200A0000004
Как я могу это сделать?
Вот мои неубедительные результаты исследований, с причинами, по которым:
Как я могу сделать 64-битную арифметику в Perl?
Как мне суммировать большие шестнадцатеричные значения в Perl? Неопределенно, ответить не окончательноточный и без примера.
Целочисленное переполнение не окончательное
Целочисленное переполнение не окончательное
bigint нет информации о назначении, арифметике или выводе
bignum примеры не близки моемупроблема.
Как я могу набрать большое число в Perl? приведенный пример не достаточно информации для меня: не имеет дело с шестнадцатеричным назначениемили арифметика.
Re: генератор секретного кода В некоторых примерах, использующих Fleximal, упоминается to_str для вывода значения переменной, но 1) Я нене вижу, как была назначена переменная, и 2) я получаю сообщение об ошибке «Не удается вызвать метод« to_str »без ссылки на пакет или объект», когда я запускаю свой код, используя его.
String to Hex Пример использования Math :: BigInt, который у меня не работает - все равно выдается ошибка переполнения.
Есть ли 64-битный гекс()? Почти там - но не имеет дело с выводом большого числа в шестнадцатеричном виде, оно говорит только о десятичном числе.
CPAN Math: Fleximal выполняет арифметику, но, кажется, нет никаких средств для фактического вывода значения в шестнадцатеричном виде
sprintf Кажется, не в состоянии справитьсяс номерами больше 32 бит, получите насыщенное сообщение FFFFFFFF.
Редактировать: Обновление - новое требование и поставляемое решение - пожалуйста, не стесняйтесь комментировать
Час.Ответ Оуэнса по-прежнему принят и превосходен (часть 2 работает для меня, я не пробовал версию 1 для более нового Perl, хотя я бы пригласил других подтвердить это).
Однако, еще одно требование было уметьпреобразовать обратно из результата в исходный идентификатор.
Итак, я написал код для этого, вот полное решение, включая @Chas.Оригинальное решение Owens с последующей реализацией для этого нового требования:
#!/usr/bin/perl
use strict;
use warnings;
use bigint;
use Carp;
sub bighex {
my $hex = shift;
my $part = qr/[0-9a-fA-F]{8}/;
croak "$hex is not a 64-bit hex number"
unless my ($high, $low) = $hex =~ /^0x($part)($part)$/;
return hex("0x$low") + (hex("0x$high") << 32);
}
sub to_bighex {
my $decimal = shift;
croak "$decimal is not an unsigned integer"
unless $decimal =~ /^[0-9]+$/;
my $high = $decimal >> 32;
my $low = $decimal & 0xFFFFFFFF;
return sprintf("%08x%08x", $high, $low);
}
for my $id (0 ,1, 2, 0xFFFFF, 0x100000, 0x100001, 0x1FFFFF, 0x200000, 0x7FDFFFFF ) {
my $result = bighex("0x00000200A0000000");
$result += ( ( $id & 0xFFFFF ) * 2 ) + ( ( $id / 0x100000 ) * 0x40000000 );
my $clusterid = to_bighex($result);
# the convert back code here:
my $clusterid_asHex = bighex("0x".$clusterid);
my $offset = $clusterid_asHex - bighex("0x00000200A0000000");
my $index_small_units = ( $offset / 2 ) & 0xFFFFF;
my $index_0x100000_units = ( $offset / 0x40000000 ) * 0x100000;
my $index = $index_0x100000_units + $index_small_units;
print "\$id = ".to_bighex( $id ).
" clusterid = ".$clusterid.
" back to \$id = ".to_bighex( $index ).
" \n";
}
Попробуйте этот код на http://ideone.com/IMsp6.