I'm trying to convert an int to binary, and then perform bitwise operations on the binary.
My current method is to take the int, call to_s(2) on it, but then I'm left with a binary string.
Any advice on what I should do?
Simple integers are stored as binary in nearly every major programming language (including Ruby). So, you can do your bitwise operations on the integers themselves:
>> 6 | 5 # bitwise or
=> 7
>> 6 & 5 # bitwise and
=> 4
>> 6 ^ 5 # bitwise xor
=> 3
>> 6 >> 2 # right shift
=> 1
>> 6 << 2 # left shift
=> 24
(Edit: this appears to be my 1000th answer.)
the_number.to_s(2).split('').map { |x| x.to_i } # convert the number to binary array
Related
I would like to access a ruby integer's sign bit directly.
Ruby allows access to an int's bits through the [] operator:
1[0] -> 1
2[1] -> 1
I tried -1[-1] (to access the last one), but that doesn't work.
You can understand this by looking at the documentation for Fixnum#[] :
Returns the +n+th bit in the binary representation of fix, where fix[0] is the least significant bit
https://ruby-doc.org/core-2.2.0/Fixnum.html#method-i-5B-5D
A Fixnum is not an array, thus its #[] function can (and does) behave differently to what you'd expect from an array.
Solution 1
To access the most significant bit you can use #bit_length - 1
> a = 5
=> 5
> a[a.bit_length - 1]
=> 1
However, this excludes the sign bit for negative numbers, so to get the sign bit, do not remove 1 from the bit_length
> a = -5
=> 5
> a[a.bit_length]
=> 1
> a = 42
=> 42
> a[a.bit_length]
=> 0
Solution 2
You could also just use a < 0 comparison:
> a = -5
=> -5
> sign_bit = a < 0 ? 1 : 0
=> 1
Solution 3
First of all, let's read the documentation for #size:
Returns the number of bytes in the machine representation of fix.
From the implementation of the function we can gather that if the stored number is inside the bounds of a 32-bit signed integer if will be stored in one. In this case #size returns 4. If it is larger it will be stored in a 64-bit integer and #size will return 8.
However not all of these bits are in use. If you store the number 5 (0b101) your 32 bits will be occupied as such
10100000 00000000 00000000 00000000
Negative numbers are most of the time stored as the 2s complement (not sure if applicable for ruby) which would mean that if you store the number -5 your 32 bits will be occupied as such
11011111 11111111 11111111 11111111
Thus you can also access the sign bit with the following code:
x[x.size * 8 - 1]
Bonus
If you're curious about why 5[-1] does not throw an exception and still returns a number, you can look at the source code for Fixnum#[] (on the documentation page previously mentioned).
if (i < 0) return INT2FIX(0);
It is made to just return 0 if your index is a negative number.
I'm testing out the reduce/inject method and ruby and came across a command with unexpected results.
(1..2).reduce(:<<) produces #=> 4
I believe I understand what reduce and inject do but I'm not understanding the << operator.
The << operator is the Binary Left Shift Operator. It will shift the bits in the binary representation of the number the amount of places you specify.
So 1 << 2 will shift all the bits of 1 left by 2 positions.
In your example code, 1 will be shifted 2 positions to the left, which is the binary representation of 4, which is the result.
<< is Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand.
e.g.
10 << 2 #=> 40.
10 binary representation is 0000 1010 will be shifted to left by 2 bits and the result will be 0010 1000 which is 40
Please let me know if this is correct way to get the cubic root.
I can't understand why
27 ** (1.0/3.0) #=> 3
is different from
27 ** (1/3) #=> 1
1.0 / 3.0 # => 0.3333333333333333
27 ** 0.333 # => 2.9967059728946346
1 / 3 # => 0
27 ** 0 # => 1
The second is an example of integer division. How many threes are there in one? Zero. Any number in power 0 is 1.
The first division is a decimal division and the latter is an integer division
that is 1.0/3.0 will yield a decimal result whereas 1/3will yield an integer result which in this case i 0
the results will therefor be different since it's the result of either
27**0.333...
or
27**0
which of course are clearly different.
It's enough to force one of the operators to be decimal for the entire operation to yield a decimal result e.g. 1/3.0 will yield 0.3333...
Integer division results in integers:
irb(main):004:0> 1/3
=> 0
irb(main):005:0> 1.0/3.0
=> 0.3333333333333333
27**0 = 1. 27**(1/3) = 3
(1/3) returns 0 since 3 is an integer. in ruby, if you divide using integers for both the divisor and dividend, you going to get an integer value. and since anything raised to 0 is 1, your get 1 as the answer
(1.0/3.0) returns 0.3333 since you're not dividing 2 integers so you get 3 from 27 ** 0.33...
Type conversation.
When you compute 1.0/3.0 - It is decimal
Which is 1.0/3.0 = 0.33 # which is a decimal
1/3 - It rounds to the nearest integer.
Thus:
27 ** (1.0/3.0) #=> 3
is different from
27 ** (1/3) #=> 1
Why does Ruby hash an integer n to 2 * n + 1?
>> [0,1,2,3].each {|x| puts x.hash}
1
3
5
7
I can see that you don't always need to have complicated hashes, especially for simple objects. But why the 'double and add 1' rule as opposed to doing what Python does, which is to hash integers to themselves?
>>> map(hash,[0,1,2,3])
[0, 1, 2, 3]
Is there a reason?
Integers are objects, so they have an object_id. But there is an infinite number of integers. Seemingly, no room for other objects. How does Ruby pull this off?
10.times{|i| puts i.object_id}
Output:
1
3
5
7
9
11
13
15
17
19
Integers take all odd object_id's, the rest of the objects go in between, they use the even numbers. The conversion from object_id (and hash) to integer (and vice versa) is very easy: chop the rightmost 1 bit (or add it).
I need to get the n-th bit of an Integer, either signed or unsigned, in Ruby.
x = 123 # that is 1111011
n = 2 # bit 2 is ...0
The following piece of code doesn't work in the general case:
x.to_s(2)[-(n+1)] #0 good! but...
because of negative numbers not represented as 2-complement:
-123.to_s(2) # "-1111011"
So how to proceed?
x = 123 # that is 1111011
n = 2 # bit 2 is ...0
x[n] # => 0
-123[2] # => 1
def f x, bit
(x & 1 << bit) > 0 ? 1 : 0
end
You could try the Bindata lib.
There is a function to represent an integer's binary representation as a string, and after that, you can do what you like with it.