Perl - 将十六进制转换为二进制并将其用作字符串
Posted
技术标签:
【中文标题】Perl - 将十六进制转换为二进制并将其用作字符串【英文标题】:Perl - convert hexadecimal to binary and use it as string 【发布时间】:2019-07-29 01:18:14 【问题描述】:我是 Perl 新手,在使用不同类型时遇到了困难。
我正在尝试获取一个十六进制寄存器,将其转换为二进制,将其用作字符串并从二进制字符串中获取子字符串。
我做了一些搜索,我尝试的是:
my $hex = 0xFA1F;
print "$hex\n";
结果是 "64031" 。第一个惊喜:我不能在 Perl 中打印十六进制值而不仅仅是十进制值吗?
$hex = hex($hex);
print "$hex\n";
结果是 409649。第二个惊喜:我希望结果也是 64031,因为“hex”将十六进制转换为十进制。
my $bin = printf("%b", $hex);
它打印二进制值。有没有办法在不打印的情况下将十六进制转换为 bin?
谢谢, SLP
【问题讨论】:
尝试在十六进制常量周围添加引号:my $hex ='0xFA1F'
。如果不是,则将其转换为数字 64031。稍后,当您执行hex(64031)
时,64031 被解释为十六进制字符串0x64031
谢谢!确实很简单......它对我有用
【参考方案1】:
十进制、二进制和十六进制都是数字的文本表示(即写入数字的方式)。计算机无法将这些作为数字来处理。
my $num = 0xFA1F;
将指定的数字(六万四千三十一)存储到$num
。它以硬件可以理解的格式存储,但这不是很重要。重要的是它存储为数字,而不是文本。
当要求print
打印一个数字时,它会以十进制(如果足够大/足够小,则以科学计数法)打印出来。它不知道数字是如何创建的(来自十六进制常数?来自加法?等),因此无法确定如何根据该数字输出。
要将数字打印为十六进制,您可以使用
my $hex = 'FA1F'; # $hex contains the hex representation of the number.
print $hex; # Prints the hex representation of the number.
或
my $num = 0xFA1F; # $num contains the number.
printf "%X", $num; # Prints the hex representation of the number.
【讨论】:
附带说明,Perl 可以处理数字的十进制表示,就好像它是一个数字一样。如果一个字符串即将用于数值运算,Perl 将首先将字符串从十进制转换为数字。这与问题无关。【参考方案2】:您正在使用十六进制格式分配一个整数值。 print
默认以十进制格式打印数字,所以你得到的是 64031。
您可以使用 printf() 通过提供不同的格式来验证这一点。
$ perl -e ' my $num = 0xFA1F; printf("%d %X %b\n", ($num) x 3 ) '
64031 FA1F 1111101000011111
$ perl -e ' my $num = 64031; printf("%d %X %b\n", ($num) x 3 ) '
64031 FA1F 1111101000011111
$ perl -e ' my $num = 0b1111101000011111; printf("%d %X %b\n", ($num) x 3 ) '
64031 FA1F 1111101000011111
$
要获取字符串中0xFA1F的二进制格式,可以使用sprintf()
$ perl -e ' my $hex = 0xFA1F; my $bin=sprintf("%b",$hex) ; print "$bin\n" '
1111101000011111
$
【讨论】:
【参考方案3】:让我们按顺序处理每一点混乱
my $hex = 0xFA1F;
这会在$hex
中存储一个十六进制常量,但是 Perl 没有十六进制数据类型,因此尽管您可以编写十六进制常量、二进制和八进制常量,但 Perl 会将它们全部转换为十进制。注意有很大的区别
my $hex = 0xFA1F;
和
my $hex = '0xFA1F';
第一个存储一个数字到 $hex,当你打印出来你会得到一个十进制数字,第二个存储一个字符串,当打印出来时会给出0xFAF1
,但可以传递给hex()
函数转换为十进制。
$hex = hex($hex);
hex 函数将 字符串 转换为十六进制数并返回十进制值,到目前为止,$hex
仅被用作 Perl 将首先使用的数字stringify $hex
然后将字符串传递给hex()
函数以将该值从十六进制转换为十进制。
所以解决方案。 printf()
几乎就在那里,有一个名为 sprintf()
的函数采用与 printf()
相同的参数,但不是打印格式化的值,而是将其作为字符串返回。所以你需要的是。
my $hex = 0xFA1F;
my $bin = sprintf("%b", $hex);
print $bin;
技术说明: 是的,我知道 Perl 在内部将其所有数字都存储为二进制,但我们不要去那里寻求这个答案,好吗?
【讨论】:
Re "Perl 将它们全部转换为十进制",不。Perl 将它们转换为计算机可以理解的格式(2 的补码)。转换为十进制(数字的文本表示)由print
完成。
@ikegami 请参阅答案底部的技术说明,我不想混淆提问者。
我想说一个完全错误的解释比其他任何事情都更容易混淆。【参考方案4】:
如果您可以使用发行版,我写了Bit::Manip 以便在处理寄存器时使我的原型设计更容易一些(如果您在编译 XS 代码时遇到问题,还可以使用Pure Perl 版本)。
它不仅可以从数字中提取位,还可以切换、清除、设置等:
use warnings;
use strict;
use Bit::Manip qw(:all);
my $register = 0xFA1F;
# fetch the bits from register using msb, lsb
my $msbyte = bit_get($register, 15, 8);
print "value: $msbyte\n";
print "bin: " . bit_bin($msbyte) . "\n";
# or simply:
# printf "bin: %b\n", $msbyte;
输出:
value: 250
bin: 11111010
这是我写的blog post,它展示了如何通过示例数据表寄存器使用该软件的某些功能。
【讨论】:
这很好,不幸的是我无法在我的电脑上下载图书馆。不过还是谢谢你的回答 @SLP 不过你可以下载!链接“Pure Perl”版本是单个文件,似乎没有依赖关系(本身不使用任何特殊库),在Perl程序中可以直接为use
d。因此,您可以从字面上下载该文件并将其放在您保留自己的模块的任何位置。就是这样,使用它。您还可以查看module code(少于 200 行!),并根据需要使用它!我敢肯定作者不会介意:)
@zdim 不,我当然不介意!这就是我使用 Perl 许可证发布所有代码的原因 :)以上是关于Perl - 将十六进制转换为二进制并将其用作字符串的主要内容,如果未能解决你的问题,请参考以下文章