我有时会用这个:
$ perl -e "printf \"%d\", ((~18446744073709551592)+1)"
24
我好像不能和Raku一起做。我能得到的最好结果是:
$ raku -e "say +^18446744073709551592"
-18446744073709551593
那么:我如何使Raku给出与Perl相同的答案?
发布于 2022-07-05 22:32:38
必须与(我的变体)Liz的自定义操作(在她下面的评论)。
sub prefix:<²^>(uint $a) { (+^ $a) + 1 }
say ²^ 18446744073709551592; # 24
我最初的“半受教育的狂野猜测”被证明是@zentrunix所接受的,也是Liz的观点的基础:
say (+^ my uint $ = 18446744073709551592) + 1; # 24
不/起作用了!
脚注
我翻转了两个字符op,因为我想要遵循+^
形式,让它成为“2的补语”,并避免它看起来像^2
。
有一种思路是关于特定整数的。我看到18446744073709551592
离2**64
很近。另一个原因是,在Perl中,整数的精度是有限的,除非您做了其他的事情,而在Raku中,它们是任意的精度,除非您做了其他的事情。第三种思路来自于阅读prefix +^
文档,其中说“使用所需的字节将数字转换为二进制”,我将其解释为表示形式在某种程度上是重要的。嗯。如果我尝试一个int
变量呢?溢出。(当然。) uint
?对啰。
我不知道这个解决方案是否正确,原因是错误的。甚至更糟。有一点值得关注的是,Raku中的uint
被定义为对应于用于编译Raku代码的Raku编译器所支持的最大本机无符号整数大小。(Iirc.)在今天的实践中,这意味着Rakudo和任何底层平台都将成为目标,我认为这几乎肯定意味着几乎所有情况下C的uint64_t
。我认为perl
有一些类似的平台相关定义。因此,我的解决方案,如果是合理的,大概只能移植到在某个平台上运行时,Raku编译器(在实践中意味着Rakudo)与perl
二进制(在实践中是指P5P的perl
)一致的程度。另见下面@p6steve的评论。
发布于 2022-07-05 21:36:36
‘长手’回答:
raku -e 'put ( (18446744073709551592.base(2) - 0b1).comb.map({!$_.Int+0}).join.parse-base(2));'
或
raku -e 'say 18446744073709551592.base(2).comb.map({!$_.Int+0}).join.parse-base(2) + 1;'
样本输出:24
上面的答案(应该?)直接实现“二补”编码。两家公司都没有使用Raku的+^
双补码运算符。第一个从二进制表示中减去一个,然后反转。第二个先倒转,然后再加一个。两种答案都没有真正正确,但得到的答案与Perl5 (24
)相同。
查看Raku Docs页面,人们会得出结论,一个正数的“两个补码”将是负数,因此不清楚Perl (以及现在的Raku)答案代表什么。希望前面的内容能有所帮助。
https://stackoverflow.com/questions/72869704
复制相似问题