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.
Related
I have a task where I need to take a number, e.g. 13002, and print it digit by digit using UART (including non-leading 0's). The UART expects that whatever it prints will go in the $s0 register but I can call it whenever I need using a jal.
This means I need to place a digit in $s0 and jump (the UART code has a jr $ra in it so it will return properly once complete.
My problem is I don't know how to iterate over the digits in the number.
My approach so far is to mod the number by 10 (Because it's a decimal number represented in binary) but that gives me the digits in reverse order.
E.g. 13002 % 10 = 2 (then divide 13002 by 10, integer division will truncate the decimal), 1300 % 10 = 0, divide again by 10, 130 ...so on and so forth.
As mentioned above however, that gives me the digits in reverse order. How would I properly iterate over the number?
I wrote some pseudocode in python but it's having trouble with numbers that have 0's in them:
def iterateOverDigits(n):
while (n >= 10):
x = n
i = 0
while (x >= 10):
x = x // 10
i += 1
print(x)
x = n
x = x % (10 ** i)
n = x
iterateOverDigits(1302) # This prints 132
In [1]: def by_digit(n):
...: for char in str(n):
...: print(char)
...:
In [2]: by_digit(120405)
1
2
0
4
0
5
In [3]:
Change the print statement to the following to remove the newlines between each digit:
print(char, end="")
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 need to convert number into their minimal log2 +1, but I have a problem, that in 32-bit Ruby, log2(8) = 2.9999999999999996
The input (pos) and output (level) should be:
1 -> 1
2-3 -> 2
4-7 -> 3
8-15 -> 4
16-31 -> 5
and so on..
My formula:
pos = 8
level = ( Math.log(pos,2) + 1 ).to_i
# 3 (wrong) in 32-bit Ruby
# 4 (correct) in 64-bit Ruby
Is there more way to prevent this from happening or is there any other formula that convert pos to correct level as shown above?
pos = 8
level = 0
until pos < 2
level += 1
pos /= 2
end
level + 1 #=> 4
Here's another interesting way to compute the floored logarithm for integers:
0.upto(Float::INFINITY).find{|e| x - base**e < base }
The maximum representable value with IEEE 754-2008 binary32 is (2−2**(−23)) × 2**127, so the base 2 log of a number stored in binary 32 is less than decimal 128. Since the round-off error is a small fraction of one, we can round to the nearest integer and see if 2 to that integer power equals the given number. If it does, return the integer power; else return nil, signifying that it is not a power of 2.
def log_2_if_integer(n)
x = Math.log(n,2).round(0).to_i
(2**x == n) ? x : nil
end
log_2_if_integer(4) #=> 2
log_2_if_integer(512) #=> 9
log_2_if_integer(3) #=> nil
In other words, because the log is less than 128, rounding error could not produce a value x such that 2**(x+m) == n for any (positive or negative) integer m != 0.
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
Given a bunch of integers, I want to convert them to base n and for each bit, add the bits up and mod them by n.
Example: Let n = 3, and suppose I want to add the bits mod 3 in 4, 4, 4, 2. These numbers in base 3 is 11, 11, 11, 02. The least significant bit adds up to 1 + 1 + 1 + 2 = 5 = 2 mod 3. The second least significant bit adds up to 1 + 1 + 1 + 0 = 3 = 0 mod 3. The answer is then 02 base 3 = 2. Alternatively, if we didn't convert to base 3 before the addition, and just did it in binary, we have 100, 100, 100, 010. The resulting bits from least significant to most significant is: 0 + 0 + 0 + 0 = 0 mod 3, 0 + 0 + 0 + 1 = 1 mod 3, 1 + 1 + 1 + 0 = 0 mod 3, so the answer is 010 = 2.
The case where n = 2 is pretty easy, you can just XOR everything. Is there a way to generalize this?
Here's a ditty in ruby:
#! /usr/bin/env ruby
def naryxor(n, terms)
puts "Calculating the #{n}-ary XOR of #{terms.join(", ")}..."
raise "Negative terms are forbidden" if terms.any? { |i| i < 0 }
xor = [] # "Digits" of our n-ary xor result
done = false
while not done
done = true # Assume we're done until proven otherwise
xor.insert(0, 0) # Insert a new total digit at the front
terms = terms.select { |i| i > 0 }.collect do |i|
done = false # Not all remaining terms were zero
digit = i % n # Find the least n-ary digit
rest = (i - digit) / n # shift it off
xor[0] += digit # add it to our xor
rest # Replace this integer with its remainder
end
xor[0] %= n # Take the mod once, after summing.
end
xor[1..-1] # Drop untouched leading digit
end
raise "Usage: ./naryxor.rb arity term term..." if ARGV.size <= 1
puts naryxor(ARGV[0].to_i, ARGV[1..-1].collect(&:to_i)).join("")
Running it:
$ ./naryxor.rb 3 4 4 4 2
Calculating the 3-ary XOR of 4, 4, 4, 2...
02
This is just expands the n-ary representations of the passed integers and does the dumb thing. If n were taken to be a power of two, we could do some more interesting bit-twiddles to avoid the integer divisions, but you gave no such guarantee.
I don't think there's a mathematical property that leads to an efficient general short-cut. The reason XOR works for base 2 is because XOR has the convenient property of being an addition with carry discard.
A simple recursive function can apply the algorithm, e.g. taking advantage of Scala's BigInt class for base conversion:
def sums(radix: Int, digits: List[List[String]]): String =
if(digits exists { _.nonEmpty }) // there's at least 1 bit left to add
(digits.flatMap { _.headOption } // take the 1st bit of all numbers
.map { BigInt(_, radix) } // convert to int representation
.sum
.toInt % radix // modulo by base
).toString +
sums(radix, digits map { _.drop(1) }) // do next most significant bit
else
"" // base case: no digits left to add
def sum(radix: Int, ns: List[Int]): Int =
BigInt(
sums(
radix,
ns // use BigInt to convert from int representation to string
.map { BigInt(_) }
.map { _.toString(radix).split("").drop(1).toList.reverse }
)
.reverse,
radix
).toInt
scala> sum(3, List(4,4,4,2))
res0: Int = 2
Your question is tagged 'performance' but doesn't lay out any additional constraints about memory or runtime to inform an improved approach.