Project

General

Profile

Actions

Bug #13711

closed

Unexpected behavior of bit_length method on negative integers

Added by jzakiya (Jabari Zakiya) about 5 years ago. Updated about 5 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:81893]

Description

The two's complement representation of negative integers produces unexpected results
when the bit_length method is applied to them.

5.bit_length => 3
4.bit_length => 3
3.bit_length => 2
2.bit_length => 2
1.bit_length => 1
0.bit_length => 0
(-1).bit_length => 0
(-2).bit_length => 1
(-3).bit_length => 2
(-4).bit_length => 2
(-5).bit_length => 3
(-6).bit_length => 3
(-7).bit_length => 3
(-8).bit_length => 3
(-9).bit_length => 4

I would have thought that bit_length on a negative integer would return the number
of bits it takes to represent a two's complement number on the given cpu/os.

Since the two's complement of negative integers are of the form:

-1 =>  111111111111111111
-2 =>  111111111111111110
-3 =>  111111111111111101
-4 =>  111111111111111100
-5 =>  111111111111111011
-6 =>  111111111111111010
-7 =>  111111111111111001
-8 =>  111111111111111000
-9 =>  111111111111110111

it thus appears for negative integers bit_length returns the bit
position of the left most 0 of the two's complement representation.

Is this correct?
Is this intentional?
If so, can an explanation of this behavior/rationale be given.

Updated by shyouhei (Shyouhei Urabe) about 5 years ago

jzakiya (Jabari Zakiya) wrote:

I would have thought that bit_length on a negative integer would return the number
of bits it takes to represent a two's complement number on the given cpu/os.

No. This is where confusion happens. Ruby's integers theoretically have infinite widths; you can express numbers far bigger than 32 or 64 bits restrictions.

Given the infinite nature of our Integers, any negative numbers theoretically have leading 111... bits forever in their 2's complement expression. If you define integer's widths as you thought, the value is always ∞.

irb(main):004:0> printf("%.10b\n", -5)
..11111011
=> nil

Here in this output, "..111" denotes that there are infinite 1s not shown due to printf's restriction.

So to give you a meaningful return value than infinity, bit_length of negative integers are defined as they are now.

Updated by jzakiya (Jabari Zakiya) about 5 years ago

Thanks for the explanation.

This morning I went and looked at the documentation for bit_length and it clearly describes its behavior.
After reading it, and your explanation, I now understand the logic for its behavior.

http://ruby-doc.org/core-2.4.1/Integer.html

bit_length → integer click to toggle source
Returns the number of bits of the value of int.

"the number of bits" means that the bit position of the highest bit which is different to the sign bit. (The bit position of the bit 2**n is n+1.) If there is no such bit (zero or minus one), zero is returned.

Updated by duerst (Martin Dürst) about 5 years ago

  • Status changed from Open to Rejected

No further action needed.

Actions

Also available in: Atom PDF