需要解释 `~0` 与 `2**64` 有无 `use integer`
Need explanation for `~0` vs. `2**64` with and without `use integer`
我写了一些测试程序打印 ~0
和 2**64
的值:
#!/usr/bin/perl
use warnings;
use strict;
#use integer;
print ~0, "\n";
print 2**64, "\n";
没有use integer
程序输出
118446744073709551615
1.184467440737096e+19
使用 use integer
程序输出:
-1
1.184467440737096e+19
另一个奇怪的事情是,即使使用 print int(2**64)
,数字仍然以科学格式输出,就像 int(...)
不存在一样(仍然 ~0
没有 use integer
以“整数格式”输出)。
不过,我可以使用 printf("%u\n", ...)
强制整数输出。
(Perl 在 x86_64 上的 SLES12 SP5 5.18.2 中使用)
问题:
那么,为什么 2**64
是有或没有 use integer
的“浮动”,而 ~0
从来不是?
并且 use integer
当 ~0
打印为 -1
时,它仍然满足条件 ~0 > 2**63
(当我期望 -1
不大于任何正值(如2**63
)。
更新
在 Perl 调试器中似乎还有另一个奇怪的效果:
2^64
是奇数,2^64-1
是-2
.
DB<22> if (1) { use integer; print 2**64, "\n" }
1.84467440737096e+19
DB<23> if (1) { use integer; print 2**64 - 1, "\n" }
-2
DB<13> if (1) { use integer; printf '%x', 2**64-1, "\n" }
fffffffffffffffe
DB<14> if (1) { use integer; printf '%x', 2**64, "\n" }
ffffffffffffffff
DB<15> if (1) { no integer; printf '%x', 2**64, "\n" }
ffffffffffffffff
DB<16> if (1) { no integer; printf '%x', 2**63, "\n" }
8000000000000000
So why is 2**64
a "float" with and without use integer
指数是使用浮点数计算的,因此产生一个浮点数。我不知道为什么 use integer
不强制将结果强制转换为有符号整数,但事实并非如此。这与其文档一致,该文档指出编译指示仅影响以下操作数和结果:
- 算术运算符(
+
、-
、*
、/
、%
、+=
、-=
, *=
, /=
, %=
, 和一元负)
- 比较运算符(
<
、<=
、>
、>=
、==
、!=
、<=>
), 和
- 按位运算符(
|
、&
、^
、<<
、>>
、|=
、&=
, ^=
, <<=
, >>=
)
其实就是特意排除了**
.
The power operator **
is also not affected, so that 2 ** .5 is always the square root of 2.
while ~0
never is?
机器只有整数类型的按位运算,而且return整数类型。将数字转换为浮点数毫无意义(并且有很多理由不使用 64 位整数构建)。
And with use integer
when ~0
is print as -1
, it still satisfies the condition ~0 > 2**63
(when I'd expect -1
not to be greater than any positive value (like 2**63
).
use integer
导致许多运算符将值转换为 IV,而 <
就是这样的运算符。转换 2**63
在我的机器上产生 -9223372036854775808。
$ perl -M5.010 -Minteger -e'say 0 + 2**63'
-9223372036854775808
手册页 perlop(1)
在“ 整数运算 ” 部分解释说 use integer
将导致对整数结果进行带符号的解释,因此这将解释 118446744073709551615
与 -1
.
另一件事是,对于 64 位整数,2**64
实际上是一个 65 位数,不能表示为整数。
所以这被解释为浮点数。
也许,最重要的是:
~0
不是 2**64
,而是 2**64 - 1
.
我无法解释的唯一影响是为什么 int floor(2**64 - 1)
不像 ~0
或 0xffffffffffffffff
那样输出为整数。
我写了一些测试程序打印 ~0
和 2**64
的值:
#!/usr/bin/perl
use warnings;
use strict;
#use integer;
print ~0, "\n";
print 2**64, "\n";
没有use integer
程序输出
118446744073709551615
1.184467440737096e+19
使用 use integer
程序输出:
-1
1.184467440737096e+19
另一个奇怪的事情是,即使使用 print int(2**64)
,数字仍然以科学格式输出,就像 int(...)
不存在一样(仍然 ~0
没有 use integer
以“整数格式”输出)。
不过,我可以使用 printf("%u\n", ...)
强制整数输出。
(Perl 在 x86_64 上的 SLES12 SP5 5.18.2 中使用)
问题:
那么,为什么 2**64
是有或没有 use integer
的“浮动”,而 ~0
从来不是?
并且 use integer
当 ~0
打印为 -1
时,它仍然满足条件 ~0 > 2**63
(当我期望 -1
不大于任何正值(如2**63
)。
更新
在 Perl 调试器中似乎还有另一个奇怪的效果:
2^64
是奇数,2^64-1
是-2
.
DB<22> if (1) { use integer; print 2**64, "\n" }
1.84467440737096e+19
DB<23> if (1) { use integer; print 2**64 - 1, "\n" }
-2
DB<13> if (1) { use integer; printf '%x', 2**64-1, "\n" }
fffffffffffffffe
DB<14> if (1) { use integer; printf '%x', 2**64, "\n" }
ffffffffffffffff
DB<15> if (1) { no integer; printf '%x', 2**64, "\n" }
ffffffffffffffff
DB<16> if (1) { no integer; printf '%x', 2**63, "\n" }
8000000000000000
So why is
2**64
a "float" with and withoutuse integer
指数是使用浮点数计算的,因此产生一个浮点数。我不知道为什么 use integer
不强制将结果强制转换为有符号整数,但事实并非如此。这与其文档一致,该文档指出编译指示仅影响以下操作数和结果:
- 算术运算符(
+
、-
、*
、/
、%
、+=
、-=
,*=
,/=
,%=
, 和一元负) - 比较运算符(
<
、<=
、>
、>=
、==
、!=
、<=>
), 和 - 按位运算符(
|
、&
、^
、<<
、>>
、|=
、&=
,^=
,<<=
,>>=
)
其实就是特意排除了**
.
The power operator
**
is also not affected, so that 2 ** .5 is always the square root of 2.
while
~0
never is?
机器只有整数类型的按位运算,而且return整数类型。将数字转换为浮点数毫无意义(并且有很多理由不使用 64 位整数构建)。
And with
use integer
when~0
is print as-1
, it still satisfies the condition~0 > 2**63
(when I'd expect-1
not to be greater than any positive value (like2**63
).
use integer
导致许多运算符将值转换为 IV,而 <
就是这样的运算符。转换 2**63
在我的机器上产生 -9223372036854775808。
$ perl -M5.010 -Minteger -e'say 0 + 2**63'
-9223372036854775808
手册页 perlop(1)
在“ 整数运算 ” 部分解释说 use integer
将导致对整数结果进行带符号的解释,因此这将解释 118446744073709551615
与 -1
.
另一件事是,对于 64 位整数,2**64
实际上是一个 65 位数,不能表示为整数。
所以这被解释为浮点数。
也许,最重要的是:
~0
不是 2**64
,而是 2**64 - 1
.
我无法解释的唯一影响是为什么 int floor(2**64 - 1)
不像 ~0
或 0xffffffffffffffff
那样输出为整数。