Perl中的最大整数 [英] Maximum integer in Perl

查看:190
本文介绍了Perl中的最大整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

设置 $ i = 0 并在增加时执行 ++ $ i 。我们将达到哪个数字?

Set $i=0 and do ++$i while it increases. Which number we would reach?

请注意,它可能与Perl中的最大整数不同(如标题中所述),因为相邻整数之间可能存在间隙大于 1

Note that it may be not the same as maximum integer in Perl (as asked in the title), because there may be gaps between adjacent integers which are greater than 1.

推荐答案

整数可以参考一系列数据类型( int16_t uint32_t 等)。这些数字可以表示没有差距。

"Integer" can refer to a family of data types (int16_t, uint32_t, etc). There's no gap in the numbers these can represent.

整数也可以指没有小数分量的数字,无论用于存储它的变量的类型如何。 ++ 将在数据类型之间无缝转换,因此这与此问题相关。

"Integer" can also refer to numbers without a fractional component, regardless of the type of the variable used to store it. ++ will seamlessly transition between data types, so this is what's relevant to this question.

浮点数可以在这个意义上存储整数,并且可以将非常大的数字存储为浮点数,而无法向它们添加一个。原因是使用以下格式存储浮动指针编号:

Floating point numbers can store integers in this sense, and it's possible to store very large numbers as floats without being able to add one to them. The reason for this is that floating pointer numbers are stored using the following form:

[+/-]1._____..._____ * 2**____

例如,假设您的花车的尾数可以存储52位在小数点后,您想要将 1 添加到 2 ** 53

For example, let's say the mantissa of your floats can store 52 bits after the decimal, and you want to add 1 to 2**53.

     __52 bits__
    /           \
  1.00000...00000  * 2**53    Large power of two
+ 1.00000...00000  * 2**0     1
--------------------------
  1.00000...00000  * 2**53
+ 0.00000...000001 * 2**53    Normalized exponents
--------------------------
  1.00000...00000  * 2**53
+ 0.00000...00000  * 2**53    What we really get due to limited number of bits
--------------------------
  1.00000...00000  * 2**53    Original large power of two

因此在使用浮点数时可能会出现差距。但是,您开始使用存储为有符号整数的数字。

So it is possible to hit a gap when using floating point numbers. However, you started with a number stored as signed integer.

$ perl -MB=svref_2object,SVf_IVisUV,SVf_NOK -e'
   $i = 0;
   $sv = svref_2object(\$i);
   print $sv->FLAGS & SVf_NOK    ? "NV\n"   # Float
      :  $sv->FLAGS & SVf_IVisUV ? "UV\n"   # Unsigned int
      :                            "IV\n";  # Signed int
'
IV

++ $ i 将该数字保留为有符号整数值(IV),直到它不再存在。此时,它将开始使用无符号整数值(UV)。

++$i will leave the number as a signed integer value ("IV") until it cannot anymore. At that point, it will start using an unsigned integer values ("UV").

$ perl -MConfig -MB=svref_2object,SVf_IVisUV,SVf_NOK -e'
   $i = hex("7F".("FF"x($Config{ivsize}-2))."FD");
   $sv = svref_2object(\$i);
   for (1..4) {
      ++$i;
      printf $sv->FLAGS & SVf_NOK    ? "NV %.0f\n"
         :   $sv->FLAGS & SVf_IVisUV ? "UV %u\n"
         :                             "IV %d\n", $i;
   }
'
IV 2147483646
IV 2147483647            <-- 2**31 - 1  Largest IV
UV 2147483648
UV 2147483649

IV 9223372036854775806
IV 9223372036854775807   <-- 2**63 - 1  Largest IV
UV 9223372036854775808
UV 9223372036854775809

仍然没有差距因为还没有使用浮点数。但Perl最终将使用浮点数(NV),因为它们的范围远大于整数。 ++ $ i 将在无符号整数用完时切换到使用浮点数。

Still no gap because no floating point numbers have been used yet. But Perl will eventually use floating point numbers ("NV") because they have a far larger range than integers. ++$i will switch to using a floating point number when it runs out of unsigned integers.

当发生这种情况取决于你的Perl构建。并非所有Perl版本都具有相同的整数和浮点数。

When that happens depends on your build of Perl. Not all builds of Perl have the same integer and floating point number sizes.

在一台机器上:

$ perl -V:[in]vsize
ivsize='4';   # 32-bit integers
nvsize='8';   # 64-bit floats

另一个:

$ perl -V:[in]vsize
ivsize='8';   # 64-bit integers
nvsize='8';   # 64-bit floats



在nvsize大于ivsize

$ b $的系统上b

在这些系统上,第一个间隙将发生在最大的无符号整数之上。如果您的系统使用IEEE双精度浮点数,则浮点数具有53位精度。它们可以无损地表示从-2 53 到2 53 (包括)的所有整数。 ++ 将无法增加。

On a system where nvsize is larger than ivsize

On these systems, the first gap will happen above the largest unsigned integer. If your system uses IEEE double-precision floats, your floats have 53-bit of precision. They can represent without loss all integers from -253 to 253 (inclusive). ++ will fail to increment beyond that.

$ perl -MConfig -MB=svref_2object,SVf_IVisUV,SVf_NOK -e'
   $i = eval($Config{nv_overflows_integers_at}) - 3;
   $sv = svref_2object(\$i);
   for (1..4) {
      ++$i;
      printf $sv->FLAGS & SVf_NOK    ? "NV %.0f\n"
         :   $sv->FLAGS & SVf_IVisUV ? "UV %u\n"
         :                             "IV %d\n", $i;
   }
'
NV 9007199254740990
NV 9007199254740991
NV 9007199254740992   <-- 2**53      Requires 1 bit of precision as a float
NV 9007199254740992   <-- 2**53 + 1  Requires 54 bits of precision as a float
                                        but only 53 are available.



在nvsize不大于ivsize的系统上



在这些系统上,第一个间隙将发生在最大的无符号整数之前。切换到浮动指针编号可以让你更进一步(2的大功率),但就是这样。 ++ 将无法超出最大无符号整数+ 1。

On a system where nvsize is no larger than ivsize

On these systems, the first gap will happen before the largest unsigned integer. Switching to floating pointer numbers will allow you to go one further (a large power of two), but that's it. ++ will fail to increment beyond the largest unsigned integer + 1.

$ perl -MConfig -MB=svref_2object,SVf_IVisUV,SVf_NOK -e'
   $i = hex(("FF"x($Config{ivsize}-1))."FD");
   $sv = svref_2object(\$i);
   for (1..4) {
      ++$i;
      printf $sv->FLAGS & SVf_NOK    ? "NV %.0f\n"
         :   $sv->FLAGS & SVf_IVisUV ? "UV %u\n"
         :                             "IV %d\n", $i;
   }
'
UV 18446744073709551614
UV 18446744073709551615   <-- 2**64 - 1  Largest UV
NV 18446744073709551616   <-- 2**64      Requires 1 bit of precision as a float
NV 18446744073709551616   <-- 2**64 + 1  Requires 65 bits of precision as a float
                                            but only 53 are available.

这篇关于Perl中的最大整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆