Split a non-power-of-two based int - math

I know that you can split a power-of-two number in half like so:
halfintR = some32bitint & 0xFFFF
halfintL = some32bitint >> 16
can you do the same thing for an integer which is bounded by a non-power of two space?
(say that you want your range to be limited to the set of integers that will fit into 4 digit base 52 space unsigned)

You could use the following
rightDigits = number % 2704 // 52 squared
leftDigits = number / 2704

Well, of course. & 0xffff is the same as % 0x10000 and >> 16 is the same as / 0x10000. It is just that division by a power-of-two is more efficient when done with bit operations like shifting and masking. Division works with any number (within range of representation).

Once you realize that the & and >> are used for doing modulo und division calculation respectively, you can write what you want as:
lower = some4DigitsNumberBase52 % (52 * 52)
upper = some4DigitaNumberBase52 / (52 * 52)
This is the basis for doing base calculation. You can also derive the solution from the algorithm that displays a number in a specific base: how do you come up with the rightmost two digits and the 2 leftmost digits.

Related

How does the modulus shorten a number to only 16 digits in this example?

I am learning Solidity by following various tutorials online. One of these tutorials is Cryptozombies. In this tutorial we create a zombie that has "dna" (a number). These numbers must be only 16 digits long to work with the code. We do this by defining
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
At some point in the lesson, we define a function that generates "random" dna by passing a string to the keccak256 hash function.
function _generateRandomDna(string memory _str) private view returns (uint) {
uint rand = uint(keccak256(abi.encodePacked(_str)));
return rand % dnaModulus;
}
I am trying to figure out how the output of keccak256 % 10^16 is always a 16 digit integer. I guess part of the problem is that I don't exactly understand what keccak256 outputs. What I (think) I know is that it outputs a 256 bit number. I bit is either 0 or 1, so there are 2^256 possible outputs from this function?
If you need more information please let me know. I think included everything relevant from the code.
Whatever keccak256(abi.encodePacked(_str)) returns, it converted into uint because of the casting uint(...).
uint rand = uint(keccak256(abi.encodePacked(_str)));
When it's an uint then the simple math, because it's modulus.
xxxxx % 100 always < 100
I see now that this code is mean to produce a number that has no more than 16 digits, not exactly 16 digits.
Take x % 10^16
If x < 10^16, then then the remainder is x, and x is by definition less than 10^16, which is the smallest possible number with 17 digits I.e. every number less than 10^16 has 16 or fewer digits.
If x = 10^16, then remainder is 0 which has fewer than 16 digits.
If x > 10^16, then either 10^16 goes into x fully or not. If it does fully, remainder is zero which has less than 16 digits, if it goes in partially, then remainder is only a part of 10^16 which will always have 16 or fewer digits.

F#: integer (%) integer - Is Calculated How?

So in my text book there is this example of a recursive function using f#
let rec gcd = function
| (0,n) -> n
| (m,n) -> gcd(n % m,m);;
with this function my text book gives the example by executing:
gcd(36,116);;
and since the m = 36 and not 0 then it ofcourse goes for the second clause like this:
gcd(116 % 36,36)
gcd(8,36)
gcd(36 % 8,8)
gcd(4,8)
gcd(8 % 4,4)
gcd(0,4)
and now hits the first clause stating this entire thing is = 4.
What i don't get is this (%)percentage sign/operator or whatever it is called in this connection. for an instance i don't get how
116 % 36 = 8
I have turned this so many times in my head now and I can't figure how this can turn into 8?
I know this is probably a silly question for those of you who knows this but I would very much appreciate your help the same.
% is a questionable version of modulo, which is the remainder of an integer division.
In the positive, you can think of % as the remainder of the division. See for example Wikipedia on Euclidean Divison. Consider 9 % 4: 4 fits into 9 twice. But two times four is only eight. Thus, there is a remainder of one.
If there are negative operands, % effectively ignores the signs to calculate the remainder and then uses the sign of the dividend as the sign of the result. This corresponds to the remainder of an integer division that rounds to zero, i.e. -2 / 3 = 0.
This is a mathematically unusual definition of division and remainder that has some bad properties. Normally, when calculating modulo n, adding or subtracting n on the input has no effect. Not so for this operator: 2 % 3 is not equal to (2 - 3) % 3.
I usually have the following defined to get useful remainders when there are negative operands:
/// Euclidean remainder, the proper modulo operation
let inline (%!) a b = (a % b + b) % b
So far, this operator was valid for all cases I have encountered where a modulo was needed, while the raw % repeatedly wasn't. For example:
When filling rows and columns from a single index, you could calculate rowNumber = index / nCols and colNumber = index % nCols. But if index and colNumber can be negative, this mapping becomes invalid, while Euclidean division and remainder remain valid.
If you want to normalize an angle to (0, 2pi), angle %! (2. * System.Math.PI) does the job, while the "normal" % might give you a headache.
Because
116 / 36 = 3
116 - (3*36) = 8
Basically, the % operator, known as the modulo operator will divide a number by other and give the rest if it can't divide any longer. Usually, the first time you would use it to understand it would be if you want to see if a number is even or odd by doing something like this in f#
let firstUsageModulo = 55 %2 =0 // false because leaves 1 not 0
When it leaves 8 the first time means that it divided you 116 with 36 and the closest integer was 8 to give.
Just to help you in future with similar problems: in IDEs such as Xamarin Studio and Visual Studio, if you hover the mouse cursor over an operator such as % you should get a tooltip, thus:
Module operator tool tip
Even if you don't understand the tool tip directly, it'll give you something to google.

How to convert decimal to hexadecimal using brain?

Since I knew how to manually convert hexadecimal to decimal using this method.
Read from right to left, the last digit multiplied by the constant value 16 and plus the first digit.
For example:
12h = 2 + (1 * 16) = 18
99h = 9 + (9 * 16) = 153
How do I convert back into hex from decimal?
As you can see in the picture above. You need to draw a table in your brain
Lets take 456 as example.
If we divide 456 by 16 . Remainder = 8 & Quotient = 28
We further divide 28 by 16 and get remainder = 12 & quotient = 1
Now further dividing 1 by 16 results in remainder = 1 and quotient = 0
So we stop.
Now we take the remainders, bottom up.
1 , 12 , 8
Converting 12 in hex notation gives C.
So the answer is 1C8
To convert from decimal to hex you must know the powers of 16. 16^1 is obviously 16; 16^2 is 256; 16^3 is 4096; 16^4 is 65536; etc.
For each power of 16, divide the number by that power to get one hex digit. Then take the remainder and divide by the next lower power of 16.
This is enough of a hassle that it's easiest to let a calculator do it, or use a scripting language such as Python.

if two n bit numbers are multiplied then the result will be maximum how bit long

I was wondering if there is any formula or way to find out much maximum bits will be required if two n bits binary number are multiplied.
I searched a lot for this but was unable to find its answer anywhere.
Number of digits in base B required for representing a number N is floor(log_B(N)+1). Logarithm has this nice property that log(X*Y)=log(X)+log(Y), which hints that the number of digits for X*Y is roughly the sum of the number of digits representing X and Y.
It can be simply concluded using examples:
11*11(since 11 is the maximum 2 bit number)=1001(4 bit)
111*111=110001(6 bit)
1111*1111=11100001(8 bit)
11111*11111=1111000001(10 bit)
and so from above we can see your answer is 2*n
The easiest way to think about this is to consider the maximum of the product, which is attained when we use the maximum of the two multiplicands.
If value x is an n-bit number, it is at most 2^n - 1. Think about this, that 2^n requires a one followed by n zeroes.
Thus the largest possible product of two n-bit numbers will be:
(2^n - 1)^2 = 2^(2n) - 2^(n+1) + 1
Now n=1 is something of a special case, since 1*1 = 1 is again a one-bit number. But in general we see that the maximum product is a 2n-bit number, whenever n > 1. E.g. if n=3, the maximum multiplicand is x=7 and the square 49 is a six-bit number.
It's worth noting that the base of the positional system doesn't matter. Whatever formula you come up with for the decimal multiplication will work for the binary multiplication.
Let's apply a bit of deduction and multiply two numbers that have relatively prime numbers of digits: 2 and 3 digits, respectively.
Smallest possible numbers:
10 * 100 = 1000 has 4 digits
Largest possible numbers:
99 * 999 = 98901 has 5 digits
So, for a multiplication of n-digit by m-digit number, we deduce that the upper and lower limits are n+m and n+m-1 digits, respectively. Let's make sure it holds for binary as well:
10 * 100 = 1000 has 4 digits
11 * 111 = 10101 has 5 digits
So, it does hold for binary, and we can expect it to hold for any base.
x has n binary digits means that 2^(n-1) <= x < 2^n, also assume that y has m binary digits. That means:
2^(m+n-2)<=x*y<2^(m+n)
So x*y can have m+n-1 or m+n digits. It easy to construct examples where both cases are possible:
m+n-1: 2*2 has 3 binary digits (m = n = 2)
m+n: 7*7=49=(binary)110001 has 6 binary digits and m = n = 3

Fast exponentiation when only first k digits are required?

This is actually for a programming contest, but I've tried really hard and haven't got even the faintest clue how to do this.
Find the first and last k digits of nm where n and m can be very large ~ 10^9.
For the last k digits I implemented modular exponentiation.
For the first k I thought of using the binomial theorem upto certain powers but that involves quite a lot of computation for factorials and I'm not sure how to find an optimal point at which n^m can be expanded as (x+y)m.
So is there any known method to find the first k digits without performing the entire calculation?
Update 1 <= k <= 9 and k will always be <= digits in nm
not sure, but the identity nm = exp10(m log10(n)) = exp(q (m log(n)/q)) where q = log(10) comes to mind, along with the fact that the first K digits of exp10(x) = the first K digits of exp10(frac(x)) where frac(x) = the fractional part of x = x - floor(x).
To be more explicit: the first K digits of nm are the first K digits of its mantissa = exp(frac(m log(n)/q) * q), where q = log(10).
Or you could even go further in this accounting exercise, and use exp((frac(m log(n)/q)-0.5) * q) * sqrt(10), which also has the same mantissa (+ hence same first K digits) so that the argument of the exp() function is centered around 0 (and between +/- 0.5 log 10 = 1.151) for speedy convergence.
(Some examples: suppose you wanted the first 5 digits of 2100. This equals the first 5 digits of exp((frac(100 log(2)/q)-0.5)*q)*sqrt(10) = 1.267650600228226. The actual value of 2100 is 1.267650600228229e+030 according to MATLAB, I don't have a bignum library handy. For the mantissa of 21,000,000,000 I get 4.612976044195602 but I don't really have a way of checking.... There's a page on Mersenne primes where someone's already done the hard work; 220996011-1 = 125,976,895,450... and my formula gives 1.259768950493908 calculated in MATLAB which fails after the 9th digit.)
I might use Taylor series (for exp and log, not for nm) along with their error bounds, and keep adding terms until the error bounds drop below the first K digits. (normally I don't use Taylor series for function approximation -- their error is optimized to be most accurate around a single point, rather than over a desired interval -- but they do have the advantage that they're mathematically simple, and you can increased accuracy to arbitrary precision simply by adding additional terms)
For logarithms I'd use whatever your favorite approximation is.
Well. We want to calculate and to get only n first digits.
Calculate by the following iterations:
You have .
Calcluate each not exactly.
The thing is that the relative error of is less
than n times relative error of a.
You want to get final relative error less than .
Thus relative error on each step may be .
Remove last digits at each step.
For example, a=2, b=16, n=1. Final relative error is 10^{-n} = 0,1.
Relative error on each step is 0,1/16 > 0,001.
Thus 3 digits is important on each step.
If n = 2, you must save 4 digits.
2 (1), 4 (2), 8 (3), 16 (4), 32 (5), 64 (6), 128 (7), 256 (8), 512 (9), 1024 (10) --> 102,
204 (11), 408 (12), 816 (13), 1632 (14) -> 163, 326 (15), 652 (16).
Answer: 6.
This algorithm has a compexity of O(b). But it is easy to change it to get
O(log b)
Suppose you truncate at each step? Not sure how accurate this would be, but, e.g., take
n=11
m=some large number
and you want the first 2 digits.
recursively:
11 x 11 -> 121, truncate -> 12 (1 truncation or rounding)
then take truncated value and raise again
12 x 11 -> 132 truncate -> 13
repeat,
(132 truncated ) x 11 -> 143.
...
and finally add #0's equivalent to the number of truncations you've done.
Have you taken a look at exponentiation by squaring? You might be able to modify one of the methods such that you only compute what's necessary.
In my last algorithms class we had to implement something similar to what you're doing and I vaguely remember that page being useful.

Resources