我需要做一些低於大十六進制數的算術,但是當我嘗試輸出時,我得到溢出錯誤消息「十六進制數字> 0xffffffff不可移植」,有關不可移植的消息或最大32位十六進制值FFFFFFFF。我該如何做64位十六進制/十進制算術,並在Perl中輸出十六進制的完整數字作爲字符串?
所有這些都意味着標準語言和輸出例程只能處理32位值。我需要64位的值並做了大量的研究,但是我沒有發現任何東西,BOTH啓用算術並輸出十六進制的大數字。
my $result = 0x00000200A0000000 +
(($id & 0xFFFFF) * 2) + (($id/0x100000) * 0x40000000);
因此,對於具有以下值$ ID,我應該得到$result
:
$id = 0, $result = 0x00000200A0000000
$id = 1, $result = 0x00000200A0000002
$id = 2, $result = 0x00000200A0000004
我怎樣才能做到這一點?
這裏是我不確定的研究成果,與理由:
How can I sum large hexadecimal values in Perl?模糊,回答不明確精確且無一例。
Integer overflow 非決定性
Integer overflow 非決定性
bigint 關於分配,運算或輸出
bignum 例子沒有接近我的問題沒有資料。
給出的例子是不夠的信息對我來說:不處理十六進制 賦值或算術。
Re: secret code generator 使用Fleximal一些例子,提到了to_str到 可變輸出值,但是1)我沒有看到 變量是如何分配的,2)我得到 錯誤「無法調用」 to_str「 沒有包或對象 參考」當我運行我的代碼使用 它。
String to Hex 使用數學:: BigInt有的例子 不爲我工作 - 仍然得到 溢出錯誤。
Is there a 64-bit hex()? 快到了 - 但不與 處理以十六進制輸出大量, 只小數會談。
CPAN Math:Fleximal 做算術,但似乎沒有要任何方式實際上 輸出十六進制仍值
sprintf 似乎並不能夠應付 數字更大比32位,得到飽和的FFFFFFFF消息的 。
編輯:更新 - 新的要求和提供的解決方案 - 請隨時提出意見
查斯。歐文斯的回答仍然被接受和優秀(第2部分爲我工作,還沒有嘗試新的Perl的第1部分版本,但我會邀請其他人來確認它)。
但是,另一個要求是能夠將返回從結果轉換爲原始ID。
所以我寫了代碼來做到這一點,下面是完整的解決方案,包括@Chas。歐文斯原來的解決方案,其次是實施這項新規定:
#!/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嘗試這個代碼。
'perl -V:ivsize'的輸出? – ysth 2010-10-06 15:39:25
這不是一個錯誤消息,它是一個警告。具體來說,你的代碼可能工作在perl使用64位整數但不使用32位整數的地方。如果實際上你有和將總是有64位整數,用'無警告'禁用它'';' – ysth 2010-10-06 15:42:48
@ysth這是一個壞主意。那麼代碼將不再是可移植的。通過關閉警告來消除警告是一種不好的做法。查看我的答案以獲得更好的解決方案 – 2010-10-06 15:46:26