In ruby, some large numbers are larger than infinity. Through binary search, I discovered:
在红宝石中,一些大数字大于无穷大。通过二进制搜索,我发现:
(1.0/0) > 10**9942066.000000001 # => false
(1.0/0) > 10**9942066 # => true
RUBY_VERSION # => "2.3.0"
Why is this? What is special about 109942066? It doesn't seem to be an arbitrary number like 9999999, it is not close to any power of two (it's approximately equivelent to 233026828.36662442).
为什么是这样? 109942066有什么特别之处?它似乎不是像9999999这样的任意数字,它不接近任何两个幂(它与233026828.36662442大致相当)。
Why isn't ruby's infinity infinite? How is 109942066 involved?
为什么红宝石的无限无限? 109942066是如何参与的?
I now realize, any number greater than 109942066 will overflow to infinity:
我现在意识到,任何大于109942066的数字都会溢出到无穷大:
10**9942066.000000001 #=> Infinity
10**9942067 #=> Infinity
But that still leaves the question: Why 109942066?
但这仍然留下了一个问题:为什么109942066?
2 个解决方案
#1
11
TL;DR
TL; DR
I did the calculations done inside numeric.c's int_pow
manually, checking where an integer overflow (and a propagation to Bignum's, including a call to rb_big_pow
) occurs. Once the call to rb_big_pow
happens there is a check whether the two intermediate values you've got in int_pow
are too large or not, and the cutoff value seems to be just around 9942066 (if you're using a base of 10 for the power). Approximately this value is close to
我手动完成了在numeric.c的int_pow中完成的计算,检查整数溢出的位置(以及对Bignum的传播,包括对rb_big_pow的调用)。一旦调用rb_big_pow,就会检查你在int_pow中得到的两个中间值是否太大,而且截止值似乎只是9942066左右(如果你使用的是10的基数) )。大约这个值接近
BIGLEN_LIMIT / ceil(log2(base^n)) * n ==
32*1024*1024 / ceil(log2(10^16)) * 16 ==
32*1024*1024 / 54 * 16 ~=
9942054
where BIGLEN_LIMIT
is an internal limit in ruby which is used as a constant to check if a power calculation would be too big or not, and is defined as 32*1024*1024
. base
is 10, and n
is the largest power-of-2 exponent for the base that would still fit inside a Fixnum.
其中BIGLEN_LIMIT是ruby中的内部限制,用作常量来检查功率计算是否太大,并定义为32 * 1024 * 1024。 base是10,n是仍然适合Fixnum的基数的最大2次幂指数。
Unfortunately I can't find a better way than this approximation, due to the algorithm used to calculate powers of big numbers, but it might be good enough to use as an upper limit if your code needs to check validity before doing exponentiation on big numbers.
不幸的是,由于用于计算大数字幂的算法,我找不到比这种近似更好的方法,但是如果你的代码需要在对大数字进行取幂之前检查有效性,那么它可能足够好用作上限。 。
Original question:
原始问题:
The problem is not with 9942066, but that with one of your number being an integer, the other one being a float. So
问题不在于9942066,而是您的一个数字是整数,另一个是浮点数。所以
(10**9942066).class # => Bignum
(10**9942066.00000001).class # => Float
The first one is representable by a specific number internally, which is smaller than Infinity
. The second one, as it's still a float is not representable by an actual number, and is simply replaced by Infinity
, which is of course not larger than Infinity
.
第一个可由内部特定数字表示,小于无限。第二个,因为它仍然是一个浮点数不能用实际数字表示,而是简单地用Infinity取代,当然它不会大于Infinity。
Updated question:
更新的问题:
You are right that there seem to be some difference around 9942066 (if you're using a 64-bit ruby under Linux, as the limits might be different under other systems). While ruby does use the GMP library to handle big numbers, it does some precheck before even going to GMP, as shown by the warnings you can receive. It will also do the exponentiation manually using GMP's mul commands, without calling GMP's pow functions.
你是正确的,在9942066周围似乎有一些差异(如果你在Linux下使用64位ruby,因为在其他系统下限制可能会有所不同)。虽然ruby确实使用GMP库来处理大数字,但是在进入GMP之前它会进行一些预检,正如您可以收到的警告所示。它还将使用GMP的mul命令手动执行取幂,而无需调用GMP的pow函数。
Fortunately the warnings are easy to catch:
幸运的是,这些警告很容易被发现:
irb(main):010:0> (10**9942066).class
=> Bignum
irb(main):005:0> (10**9942067).class
(irb):5: warning: in a**b, b may be too big
=> Float
And then you can actually check where these warnings are emitted inside ruby's bignum.c library.
然后你可以实际检查在ruby的bignum.c库中发出这些警告的位置。
But first we need to get to the Bignum realm, as both of our numbers are simple Fixnums. The initial part of the calculation, and the "upgrade" from fixnum to bignum is done inside numeric.c. Ruby does quick exponentiation, and at every step it checks whether the result would still fit into a Fixnum (which is 2 bits less than the system bitsize: 62 bits on a 64 bit machine). If not, it will then convert the values to the Bignum realm, and continues the calculations there. We are interested at the point where this conversion happens, so let's try to figure out when it does in our 10^9942066
example (I'm using x,y,z variables as present inside the ruby's numeric.c code):
但首先我们需要进入Bignum领域,因为我们的两个数字都是简单的Fixnums。计算的初始部分和从fixnum到bignum的“升级”在numeric.c中完成。 Ruby执行快速取幂,并在每一步检查结果是否仍然适合Fixnum(比系统bitsize小2位:64位机器上的62位)。如果没有,它会将值转换为Bignum领域,并在那里继续计算。我们感兴趣的是这种转换发生的地方,所以让我们试着弄清楚它在10 ^ 9942066示例中的作用(我使用的是x,y,z变量,如ruby的numeric.c代码中所示):
x = 10^1 z = 10^0 y = 9942066
x = 10^2 z = 10^0 y = 4971033
x = 10^2 z = 10^2 y = 4971032
x = 10^4 z = 10^2 y = 2485516
x = 10^8 z = 10^2 y = 1242758
x = 10^16 z = 10^2 y = 621379
x = 10^16 z = 10^18 y = 621378
x = OWFL
At this point x will overflow (10^32 > 2^62-1
), so the process will continue on the Bignum realm by calculating x**y
, which is (10^16)^621378
(which are actually still both Fixnums at this stage)
此时x将溢出(10 ^ 32> 2 ^ 62-1),因此该过程将通过计算x ** y继续在Bignum领域,即(10 ^ 16)^ 621378(实际上它们仍然是Fixnums在这个阶段)
If you now go back to bignum.c and check how it determines if a number is too large or not, you can see that it will check the number of bits required to hold x
, and multiply this number with y
. If the result is larger than 32*1024*1024
, it will then fail (emit a warning and does the calculations using basic floats).
如果你现在回到bignum.c并检查它是如何确定一个数字是否太大,你可以看到它将检查保持x所需的位数,并将该数字乘以y。如果结果大于32 * 1024 * 1024,则它将失败(发出警告并使用基本浮点数进行计算)。
(10^16)
is 54 bits (ceil(log_2(10^16)) == 54
), 54*621378
is 33554412. This is only slightly smaller than 33554432 (by 20), the limit after which ruby will not do Bignum exponentiation, but simply convert y
to double, and hope for the best (which will obviously fail, and just return Infinity
)
(10 ^ 16)是54位(ceil(log_2(10 ^ 16))== 54),54 * 621378是33554412.这只是略小于33554432(按20),之后ruby不会做Bignum的限制取幂,但简单地将y转换为double,并希望最好(显然会失败,只返回Infinity)
Now let's try to check this with 9942067:
现在让我们尝试使用9942067进行检查:
x = 10^1 z = 10^0 y = 9942067
x = 10^1 z = 10^1 y = 9942066
x = 10^2 z = 10^1 y = 4971033
x = 10^2 z = 10^3 y = 4971032
x = 10^4 z = 10^3 y = 2485516
x = 10^8 z = 10^3 y = 1242758
x = 10^16 z = 10^3 y = 621379
x = 10^16 z = OWFL
Here, at the point z overflows (10^19 > 2^62-1
), the calculation will continue on the Bignum realm, and will calculate x**y
. Note that here it will calculate (10^16)^621379
, and while (10^16)
is still 54 bits, 54*621379
is 33554466, which is larger than 33554432 (by 34). As it's larger you'll get the warning, and ruby will only to calculations using double, hence the result is Infinity
.
这里,在z溢出点(10 ^ 19> 2 ^ 62-1),计算将在Bignum领域继续,并将计算x ** y。注意,这里它将计算(10 ^ 16)^ 621379,而(10 ^ 16)仍然是54位,54 * 621379是33554466,其大于33554432(由34)。因为它越大你就会得到警告,而ruby只会使用double进行计算,因此结果就是Infinity。
Note that these checks are only done if you are using the power function. That's why you can still do (10**9942066)*10
, as similar checks are not present when doing plain multiplication, meaning you could implement your own quick exponentiation method in ruby, in which case it will still work with larger values, although you won't have this safety check anymore. See for example this quick implementation:
请注意,只有在使用电源功能时才会执行这些检查。这就是为什么你仍然可以做(10 ** 9942066)* 10,因为在进行简单乘法时不存在类似的检查,这意味着你可以在ruby中实现自己的快速取幂方法,在这种情况下它仍然可以使用更大的值,尽管你不会再进行这种安全检查了。例如,参见这个快速实现:
def unbounded_pow(x,n)
if n < 0
x = 1.0 / x
n = -n
end
return 1 if n == 0
y = 1
while n > 1
if n.even?
x = x*x
n = n/2
else
y = x*y
x = x*x
n = (n-1)/2
end
end
x*y
end
puts (10**9942066) == (unbounded_pow(10,9942066)) # => true
puts (10**9942067) == (unbounded_pow(10,9942067)) # => false
puts ((10**9942066)*10) == (unbounded_pow(10,9942067)) # => true
But how would I know the cutoff for a specific base?
但我怎么知道特定基地的截止值?
My math is not exactly great, but I can tell a way to approximate where the cutoff value will be. If you check the above calls you can see the conversion between Fixnum and Bignum happens when the intermediate base reaches the limit of Fixnum. The intermediate base at this stage will always have an exponent which is a power of 2, so you just have to maximize this value. For example let's try to figure out the maximum cutoff value for 12.
我的数学并不是很好,但我可以告诉一种方法来估算截止值的位置。如果检查上述调用,您可以看到Fixnum和Bignum之间的转换发生在中间基数达到Fixnum的限制时。此阶段的中间基数将始终具有2的幂的指数,因此您只需最大化此值。例如,让我们试着找出12的最大截止值。
First we have to check what is the highest base we can store in a Fixnum:
首先,我们必须检查我们可以在Fixnum中存储的最高基数:
ceil(log2(12^1)) = 4
ceil(log2(12^2)) = 8
ceil(log2(12^4)) = 15
ceil(log2(12^8)) = 29
ceil(log2(12^16)) = 58
ceil(log2(12^32)) = 115
We can see 12^16
is the max we can store in 62 bits, or if we're using a 32 bit machine 12^8
will fit into 30 bits (ruby's Fixnums can store values up to two bits less than the machine size limit).
我们可以看到12 ^ 16是我们可以存储在62位中的最大值,或者如果我们使用32位机器,12 ^ 8将适合30位(ruby的Fixnums可以存储比机器大小限制小两位的值) )。
For 12^16
we can easily determine the cutoff value. It will be 32*1024*1024 / ceil(log2(12^16))
, which is 33554432 / 58 ~= 578525
. We can easily check this in ruby now:
对于12 ^ 16,我们可以轻松确定截止值。它将是32 * 1024 * 1024 / ceil(log2(12 ^ 16)),这是33554432 / 58~ = 578525.我们现在可以在ruby中轻松检查:
irb(main):004:0> ((12**16)**578525).class
=> Bignum
irb(main):005:0> ((12**16)**578526).class
(irb):5: warning: in a**b, b may be too big
=> Float
Now we hate to go back to our original base of 12
. There the cutoff will be around 578525*16
(16 being the exponent of the new base), which is 9256400
. If you check in ruby, the values are actually quite close to this number:
现在我们讨厌回到12的原始基数。那里的截止值将在578525 * 16左右(16是新基数的指数),即9256400.如果你检查红宝石,这些值实际上非常接近这个号码:
irb(main):009:0> (12**9256401).class
=> Bignum
irb(main):010:0> (12**9256402).class
(irb):10: warning: in a**b, b may be too big
=> Float
#2
2
Note that the problem is not with the number but with the operation, as told by the warning you get.
请注意,问题不在于数字,而在于操作,正如您收到的警告所述。
$ ruby -e 'puts (1.0/0) > 10**9942067'
-e:1: warning: in a**b, b may be too big
false
The problem is 10**9942067
breaks Ruby's power function. Instead of throwing an exception, which would be a better behavior, it erroneously results in infinity.
问题是10 ** 9942067打破了Ruby的电源功能。它不是抛出异常,而是一种更好的行为,而是错误地导致无穷大。
$ ruby -e 'puts 10**9942067'
-e:1: warning: in a**b, b may be too big
Infinity
The other answer explains why this happens near 10e9942067.
另一个答案解释了为什么这发生在10e9942067附近。
10**9942067
is not greater than infinity, it is erroneously resulting in infinity. This is a bad habit of a lot of math libraries that makes mathematicians claw their eyeballs out in frustration.
10 ** 9942067不大于无穷大,它错误地导致无穷大。这是许多数学图书馆的坏习惯,这使得数学家们在沮丧中抓住了他们的眼球。
Infinity is not greater than infinity, they're equal, so your greater than check is false. You can see this by checking if they're equal.
无穷大不大于无穷大,它们是相等的,所以你的大于支票是假的。你可以通过检查它们是否相等来看到这一点。
$ ruby -e 'puts (1.0/0) == 10**9942067'
-e:1: warning: in a**b, b may be too big
true
Contrast this with specifying the number directly using scientific notation. Now Ruby doesn't have to do math on huge numbers, it just knows that any real number is less than infinity.
将此与直接使用科学记数法指定数字进行对比。现在Ruby不需要对数字做数学,它只知道任何实数都小于无穷大。
$ ruby -e 'puts (1.0/0) > 10e9942067'
false
Now you can put on as big an exponent as you like.
现在你可以根据自己的喜好选择一个大的指数。
$ ruby -e 'puts (1.0/0) > 10e994206700000000000000000000000000000000'
false
#1
11
TL;DR
TL; DR
I did the calculations done inside numeric.c's int_pow
manually, checking where an integer overflow (and a propagation to Bignum's, including a call to rb_big_pow
) occurs. Once the call to rb_big_pow
happens there is a check whether the two intermediate values you've got in int_pow
are too large or not, and the cutoff value seems to be just around 9942066 (if you're using a base of 10 for the power). Approximately this value is close to
我手动完成了在numeric.c的int_pow中完成的计算,检查整数溢出的位置(以及对Bignum的传播,包括对rb_big_pow的调用)。一旦调用rb_big_pow,就会检查你在int_pow中得到的两个中间值是否太大,而且截止值似乎只是9942066左右(如果你使用的是10的基数) )。大约这个值接近
BIGLEN_LIMIT / ceil(log2(base^n)) * n ==
32*1024*1024 / ceil(log2(10^16)) * 16 ==
32*1024*1024 / 54 * 16 ~=
9942054
where BIGLEN_LIMIT
is an internal limit in ruby which is used as a constant to check if a power calculation would be too big or not, and is defined as 32*1024*1024
. base
is 10, and n
is the largest power-of-2 exponent for the base that would still fit inside a Fixnum.
其中BIGLEN_LIMIT是ruby中的内部限制,用作常量来检查功率计算是否太大,并定义为32 * 1024 * 1024。 base是10,n是仍然适合Fixnum的基数的最大2次幂指数。
Unfortunately I can't find a better way than this approximation, due to the algorithm used to calculate powers of big numbers, but it might be good enough to use as an upper limit if your code needs to check validity before doing exponentiation on big numbers.
不幸的是,由于用于计算大数字幂的算法,我找不到比这种近似更好的方法,但是如果你的代码需要在对大数字进行取幂之前检查有效性,那么它可能足够好用作上限。 。
Original question:
原始问题:
The problem is not with 9942066, but that with one of your number being an integer, the other one being a float. So
问题不在于9942066,而是您的一个数字是整数,另一个是浮点数。所以
(10**9942066).class # => Bignum
(10**9942066.00000001).class # => Float
The first one is representable by a specific number internally, which is smaller than Infinity
. The second one, as it's still a float is not representable by an actual number, and is simply replaced by Infinity
, which is of course not larger than Infinity
.
第一个可由内部特定数字表示,小于无限。第二个,因为它仍然是一个浮点数不能用实际数字表示,而是简单地用Infinity取代,当然它不会大于Infinity。
Updated question:
更新的问题:
You are right that there seem to be some difference around 9942066 (if you're using a 64-bit ruby under Linux, as the limits might be different under other systems). While ruby does use the GMP library to handle big numbers, it does some precheck before even going to GMP, as shown by the warnings you can receive. It will also do the exponentiation manually using GMP's mul commands, without calling GMP's pow functions.
你是正确的,在9942066周围似乎有一些差异(如果你在Linux下使用64位ruby,因为在其他系统下限制可能会有所不同)。虽然ruby确实使用GMP库来处理大数字,但是在进入GMP之前它会进行一些预检,正如您可以收到的警告所示。它还将使用GMP的mul命令手动执行取幂,而无需调用GMP的pow函数。
Fortunately the warnings are easy to catch:
幸运的是,这些警告很容易被发现:
irb(main):010:0> (10**9942066).class
=> Bignum
irb(main):005:0> (10**9942067).class
(irb):5: warning: in a**b, b may be too big
=> Float
And then you can actually check where these warnings are emitted inside ruby's bignum.c library.
然后你可以实际检查在ruby的bignum.c库中发出这些警告的位置。
But first we need to get to the Bignum realm, as both of our numbers are simple Fixnums. The initial part of the calculation, and the "upgrade" from fixnum to bignum is done inside numeric.c. Ruby does quick exponentiation, and at every step it checks whether the result would still fit into a Fixnum (which is 2 bits less than the system bitsize: 62 bits on a 64 bit machine). If not, it will then convert the values to the Bignum realm, and continues the calculations there. We are interested at the point where this conversion happens, so let's try to figure out when it does in our 10^9942066
example (I'm using x,y,z variables as present inside the ruby's numeric.c code):
但首先我们需要进入Bignum领域,因为我们的两个数字都是简单的Fixnums。计算的初始部分和从fixnum到bignum的“升级”在numeric.c中完成。 Ruby执行快速取幂,并在每一步检查结果是否仍然适合Fixnum(比系统bitsize小2位:64位机器上的62位)。如果没有,它会将值转换为Bignum领域,并在那里继续计算。我们感兴趣的是这种转换发生的地方,所以让我们试着弄清楚它在10 ^ 9942066示例中的作用(我使用的是x,y,z变量,如ruby的numeric.c代码中所示):
x = 10^1 z = 10^0 y = 9942066
x = 10^2 z = 10^0 y = 4971033
x = 10^2 z = 10^2 y = 4971032
x = 10^4 z = 10^2 y = 2485516
x = 10^8 z = 10^2 y = 1242758
x = 10^16 z = 10^2 y = 621379
x = 10^16 z = 10^18 y = 621378
x = OWFL
At this point x will overflow (10^32 > 2^62-1
), so the process will continue on the Bignum realm by calculating x**y
, which is (10^16)^621378
(which are actually still both Fixnums at this stage)
此时x将溢出(10 ^ 32> 2 ^ 62-1),因此该过程将通过计算x ** y继续在Bignum领域,即(10 ^ 16)^ 621378(实际上它们仍然是Fixnums在这个阶段)
If you now go back to bignum.c and check how it determines if a number is too large or not, you can see that it will check the number of bits required to hold x
, and multiply this number with y
. If the result is larger than 32*1024*1024
, it will then fail (emit a warning and does the calculations using basic floats).
如果你现在回到bignum.c并检查它是如何确定一个数字是否太大,你可以看到它将检查保持x所需的位数,并将该数字乘以y。如果结果大于32 * 1024 * 1024,则它将失败(发出警告并使用基本浮点数进行计算)。
(10^16)
is 54 bits (ceil(log_2(10^16)) == 54
), 54*621378
is 33554412. This is only slightly smaller than 33554432 (by 20), the limit after which ruby will not do Bignum exponentiation, but simply convert y
to double, and hope for the best (which will obviously fail, and just return Infinity
)
(10 ^ 16)是54位(ceil(log_2(10 ^ 16))== 54),54 * 621378是33554412.这只是略小于33554432(按20),之后ruby不会做Bignum的限制取幂,但简单地将y转换为double,并希望最好(显然会失败,只返回Infinity)
Now let's try to check this with 9942067:
现在让我们尝试使用9942067进行检查:
x = 10^1 z = 10^0 y = 9942067
x = 10^1 z = 10^1 y = 9942066
x = 10^2 z = 10^1 y = 4971033
x = 10^2 z = 10^3 y = 4971032
x = 10^4 z = 10^3 y = 2485516
x = 10^8 z = 10^3 y = 1242758
x = 10^16 z = 10^3 y = 621379
x = 10^16 z = OWFL
Here, at the point z overflows (10^19 > 2^62-1
), the calculation will continue on the Bignum realm, and will calculate x**y
. Note that here it will calculate (10^16)^621379
, and while (10^16)
is still 54 bits, 54*621379
is 33554466, which is larger than 33554432 (by 34). As it's larger you'll get the warning, and ruby will only to calculations using double, hence the result is Infinity
.
这里,在z溢出点(10 ^ 19> 2 ^ 62-1),计算将在Bignum领域继续,并将计算x ** y。注意,这里它将计算(10 ^ 16)^ 621379,而(10 ^ 16)仍然是54位,54 * 621379是33554466,其大于33554432(由34)。因为它越大你就会得到警告,而ruby只会使用double进行计算,因此结果就是Infinity。
Note that these checks are only done if you are using the power function. That's why you can still do (10**9942066)*10
, as similar checks are not present when doing plain multiplication, meaning you could implement your own quick exponentiation method in ruby, in which case it will still work with larger values, although you won't have this safety check anymore. See for example this quick implementation:
请注意,只有在使用电源功能时才会执行这些检查。这就是为什么你仍然可以做(10 ** 9942066)* 10,因为在进行简单乘法时不存在类似的检查,这意味着你可以在ruby中实现自己的快速取幂方法,在这种情况下它仍然可以使用更大的值,尽管你不会再进行这种安全检查了。例如,参见这个快速实现:
def unbounded_pow(x,n)
if n < 0
x = 1.0 / x
n = -n
end
return 1 if n == 0
y = 1
while n > 1
if n.even?
x = x*x
n = n/2
else
y = x*y
x = x*x
n = (n-1)/2
end
end
x*y
end
puts (10**9942066) == (unbounded_pow(10,9942066)) # => true
puts (10**9942067) == (unbounded_pow(10,9942067)) # => false
puts ((10**9942066)*10) == (unbounded_pow(10,9942067)) # => true
But how would I know the cutoff for a specific base?
但我怎么知道特定基地的截止值?
My math is not exactly great, but I can tell a way to approximate where the cutoff value will be. If you check the above calls you can see the conversion between Fixnum and Bignum happens when the intermediate base reaches the limit of Fixnum. The intermediate base at this stage will always have an exponent which is a power of 2, so you just have to maximize this value. For example let's try to figure out the maximum cutoff value for 12.
我的数学并不是很好,但我可以告诉一种方法来估算截止值的位置。如果检查上述调用,您可以看到Fixnum和Bignum之间的转换发生在中间基数达到Fixnum的限制时。此阶段的中间基数将始终具有2的幂的指数,因此您只需最大化此值。例如,让我们试着找出12的最大截止值。
First we have to check what is the highest base we can store in a Fixnum:
首先,我们必须检查我们可以在Fixnum中存储的最高基数:
ceil(log2(12^1)) = 4
ceil(log2(12^2)) = 8
ceil(log2(12^4)) = 15
ceil(log2(12^8)) = 29
ceil(log2(12^16)) = 58
ceil(log2(12^32)) = 115
We can see 12^16
is the max we can store in 62 bits, or if we're using a 32 bit machine 12^8
will fit into 30 bits (ruby's Fixnums can store values up to two bits less than the machine size limit).
我们可以看到12 ^ 16是我们可以存储在62位中的最大值,或者如果我们使用32位机器,12 ^ 8将适合30位(ruby的Fixnums可以存储比机器大小限制小两位的值) )。
For 12^16
we can easily determine the cutoff value. It will be 32*1024*1024 / ceil(log2(12^16))
, which is 33554432 / 58 ~= 578525
. We can easily check this in ruby now:
对于12 ^ 16,我们可以轻松确定截止值。它将是32 * 1024 * 1024 / ceil(log2(12 ^ 16)),这是33554432 / 58~ = 578525.我们现在可以在ruby中轻松检查:
irb(main):004:0> ((12**16)**578525).class
=> Bignum
irb(main):005:0> ((12**16)**578526).class
(irb):5: warning: in a**b, b may be too big
=> Float
Now we hate to go back to our original base of 12
. There the cutoff will be around 578525*16
(16 being the exponent of the new base), which is 9256400
. If you check in ruby, the values are actually quite close to this number:
现在我们讨厌回到12的原始基数。那里的截止值将在578525 * 16左右(16是新基数的指数),即9256400.如果你检查红宝石,这些值实际上非常接近这个号码:
irb(main):009:0> (12**9256401).class
=> Bignum
irb(main):010:0> (12**9256402).class
(irb):10: warning: in a**b, b may be too big
=> Float
#2
2
Note that the problem is not with the number but with the operation, as told by the warning you get.
请注意,问题不在于数字,而在于操作,正如您收到的警告所述。
$ ruby -e 'puts (1.0/0) > 10**9942067'
-e:1: warning: in a**b, b may be too big
false
The problem is 10**9942067
breaks Ruby's power function. Instead of throwing an exception, which would be a better behavior, it erroneously results in infinity.
问题是10 ** 9942067打破了Ruby的电源功能。它不是抛出异常,而是一种更好的行为,而是错误地导致无穷大。
$ ruby -e 'puts 10**9942067'
-e:1: warning: in a**b, b may be too big
Infinity
The other answer explains why this happens near 10e9942067.
另一个答案解释了为什么这发生在10e9942067附近。
10**9942067
is not greater than infinity, it is erroneously resulting in infinity. This is a bad habit of a lot of math libraries that makes mathematicians claw their eyeballs out in frustration.
10 ** 9942067不大于无穷大,它错误地导致无穷大。这是许多数学图书馆的坏习惯,这使得数学家们在沮丧中抓住了他们的眼球。
Infinity is not greater than infinity, they're equal, so your greater than check is false. You can see this by checking if they're equal.
无穷大不大于无穷大,它们是相等的,所以你的大于支票是假的。你可以通过检查它们是否相等来看到这一点。
$ ruby -e 'puts (1.0/0) == 10**9942067'
-e:1: warning: in a**b, b may be too big
true
Contrast this with specifying the number directly using scientific notation. Now Ruby doesn't have to do math on huge numbers, it just knows that any real number is less than infinity.
将此与直接使用科学记数法指定数字进行对比。现在Ruby不需要对数字做数学,它只知道任何实数都小于无穷大。
$ ruby -e 'puts (1.0/0) > 10e9942067'
false
Now you can put on as big an exponent as you like.
现在你可以根据自己的喜好选择一个大的指数。
$ ruby -e 'puts (1.0/0) > 10e994206700000000000000000000000000000000'
false