Tcl:将整数转换为任意长度的二进制字符串

3
我需要一种将十进制整数转换为二进制形式的方法。必须能够指定输出二进制字符串的位长度。如果长度超过输入表示所需的位数,则额外的位将根据输入的符号填充0或1。如果指定的位长度对于输入数字来说太小,则该过程必须生成错误。
我认为在TCL中应该存在使用“二进制格式”程序的解决方案,但它让我感到困惑。似乎该程序将其转换为十六进制。我不确定TCL是否可以使用内置函数直接以我需要的方式进行转换,还是必须编写自定义程序并逐步执行。

1
你想让65变成A还是01000001或其他什么? - Donal Fellows
2个回答

4

format 命令可将数字表示为二进制形式:

set num 42
set width 10
puts [format "%0*b" $width $num]
# => 0000101010

set num -42
puts [format "%0*b" $width $num]
# => 1111111111111111111111111111111111111111111111111111111111010110

format 是 Tcl 中的 sprintf


%b 是在 Tcl 8.6 中引入的。

这段代码改编自http://rosettacode.org/wiki/Binary_digits#Tcl

proc num2bin {num width} {
    binary scan [binary format "I" $num] "B*" binval
    return [string range $binval end-$width end]
}

num2bin 42 10
# => 00000101010

说实话,我也觉得二进制格式/扫描很令人困惑。


另一种方法:

set num 42
set wid
set bin_digits {}

while {$num > 0} {
    lappend bin_digits [expr {$num % 2}]
    set n [expr {$num / 2}]
}
set binval [join [lreverse $bin_digits] ""]

puts [format {%0*s} $width $binval]

我不知道为什么我总是卡在这些表面上看起来微不足道的问题上,二进制、二进制格式、扫描和其他很多东西都混在一起变得很困惑。为什么我们在这里使用“格式”而不是“二进制格式”? - gyuunyuu
也许我误解了你的问题:你想将一个数字转换为一串二进制数,以供人类观看?还是你想将二进制数据写入文件以供机器消费?我假设是前者。 - glenn jackman
是的,它是将数字转换为位字符串,然后写入文件。二进制字符串是我需要的,当输入7时变为111,我们可以填充得到00000111。 - gyuunyuu
所以,尽管我确信这应该可以工作,但实际上我却遇到了错误“bad field specifier "b"”,这是否与TCL的版本有关?我使用的是8.5版本,由于它被锁定在Xilinx Vivado工具中,无法升级。 - gyuunyuu
是的,现在它可以使用正数了。代码需要进行一些小的排版更正,但论坛不允许我这样做。为了让它也适用于负数,我想要取绝对值,运行上述算法,然后如果操作数一直都是负数,就返回二进制补码。我认为这应该就是解决方法了,您觉得呢? - gyuunyuu

2

如果您使用的tcl版本过旧,无法支持%b格式,则可以使用一个proc来模拟它,该proc会逐位查看:

# Positive numbers only
proc num2binary {n width} {
    set bin ""
    while {$n > 0} {
        # Or set bin [string cat [expr {$n & 1}] $bin] in 8.6
        set bin "[expr {$n & 1}]$bin" 
        set n [expr {$n >> 1}]
    }
    format "%0*s" $width $bin
}

puts [num2binary 42 10]

这个版本使用位运算和字符串代替了像Glenn那样的模数/除法和列表。如果有需要,可能会更有效率。


谢谢,但负整数怎么办? - gyuunyuu
取决于你想要如何表示它们。 - Shawn
好的,所以负数将以基数10输入,然后输出必须使用指定数量的位的二进制表示。标准方法是取负数的绝对值,转换为二进制,反转位并加1以获得2的补码。现在我不确定如何在TCL中实现二进制位串上的反转位和加1。我的意思是它是一个二进制位串而不是一个数字,因此不清楚如何进行下一步操作。 - gyuunyuu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接