C# formula to determine index - c#

I have a maths issue within my program. I think the problem is simple but I'm not sure what terms to use, hence my own searches returned nothing useful.
I receive some values in a method, the only thing I know (in terms of logic) is the numbers will be something which can be duplicated.
In other words, the numbers I could receive are predictable and would be one of the following
1
2
4
16
256
65536
etc
I need to know at what index they appear at. In othewords, 1 is always at index 0, 2 at index 1, 4 at index 3, 16 is at index 4 etc.
I know I could write a big switch statement but I was hoping a formula would be tidier. Do you know if one exists or any clues as the names of the math forumula's I'm using.

The numbers you listed are powers of two. The inverse function of raising a number to a power is the logarithm, so that's what you use to go backwards from (using your terminology here) a number to an index.
var num = 256;
var ind = Math.Log(num, 2);
Above, ind is the base-2 logarithm of num. This code will work for any base; just substitute that base for 2. If you are only going to be working with powers of 2 then you can use a special-case solution that is faster based on the bitwise representation of your input; see What's the quickest way to compute log2 of an integer in C#?

Try
Math.Log(num, base)
where base is 2
MSDN: http://msdn.microsoft.com/en-us/library/hd50b6h5.aspx
Logarithm will return to You power of base from you number.
But it's in case if your number really are power of 2,
otherwise you have to understand exactly what you have, what you need
It also look like numbers was powered to 2 twice, so that try this:
private static int getIndexOfSeries(UInt64 aNum)
{
if (aNum == 1)
return 0;
else if (aNum == 2)
return 1;
else
{
int lNum = (int)Math.Log(aNum, 2);
return 1+(int)Math.Log(lNum, 2);
}
}
Result for UInt64[] Arr = new UInt64[] { 1, 2, 4, 16, 256, 65536, 4294967296 } is:
Num[0] = 1
Num[1] = 2
Num[2] = 4
Num[3] = 16
Num[4] = 256
Num[5] = 65536
Num[6] = 4294967296 //65536*65536
where [i] - index

You should calculate the base 2 logarithm of the number

Hint: For the results:
0 2
1 4
2 16
3 256
4 65536
5 4294967296
etc.
The formula is, for a give integer x:
Math.Pow(2, Math.Pow(2, x));
that is
2 to the power (2 to the power (x) )
Once the formula is known, one could solve it for x (I won't go through that since you already got an answer).

Related

Fastest way to get the first 5 digits of a BigInteger

Suppose n is a BigInteger and I want its first 5 digits. I'm thinking in 2 ways:
Dividing n by 10 log10(n)-5 times (so only the first 5 digits would remain).
Get the Substring(0, 5) of n's string.
I have no idea which one is faster or if there is another option that may be better than these.
I would like to hear considerations about it before I test these options (what do you think of them, if there is something better, etc.).
If we want to find out first 5 leading digits, we can exploit integer division:
123 / 1 == 123
12345 / 1 == 12345
1234567 / 100 == 12345
Naive approach is to divide original value by 10 while it is bigger or equal 1_000_000:
1234567 => 123456 => 12345
However, division is expensive especially if we have a huge number (if we have a number with ~1000000 digits we have to divide this number ~1000000 times). To create a faster solution
we can compute an appropriate power of 10 (power computation is fast) and then divide just once:
1234567 / Pow(10, Log10(1234567) - 5 + 1)
So the raw idea is
result = source / BigInteger.Pow(10, (int)BigInteger.Log10(source) - 4);
There are two difficulties here:
Negative numbers (we should take absolute value of source at least when we computing logarithms)
Rounding errors for huge source (what if we have rounding up and have just 4 digits?)
To cope with both problems I compute Log10 myself as Log10(2) * Log2(source):
value.GetBitLength() * 0.30102999566398
this guarantees that I have at least 5 digits but may be 6 in case of rounding errors (note 0.30102999566398 < Log10(2)).
Combining all together:
private static int FirstDigits(BigInteger value) {
if (value.IsZero)
return 0;
int digits = 5;
int result = (int)(value /
BigInteger.Pow(10, (int)(value.GetBitLength() * 0.30102999566398 - digits + 1)));
while (result >= 1_000_000 || result <= -1_000_000)
result /= 10;
return result;
}

C# - Constantly adding 9 digits

As the title says, I'm developing in C#.
I'd like to generate a number which has more than 9 numbers, so I thought about generating numbers, follow by 9.
For instance, if I want to generate a number which has 10 digits - I'd generate first a number which has 9 numbers, and then a number which has 1 digit.
If I generate the number 20, I'd generate first 2 numbers with 9 digits each, and then a number with 2 digits.
This is what I've tried:
for (int i = 0, j = (int.Parse(inputRandom.Text) % 9 == 0 ? int.Parse(inputRandom.Text) % 9 : int.Parse(inputRandom.Text) % 9 + 1); i < j; i++)
if (i < (int.Parse(inputRandom.Text) % 9 == 0 ? j % 9 : j % 9 + 1) - 1)
numToSend += (BigInteger)r.Next(int.Parse(1 + Zero((int.Parse(inputRandom.Text) % 9 + 8) * (inputRandom.Text.Length - 1))));
else
numToSend += (BigInteger)r.Next(int.Parse(1 + Zero(int.Parse(inputRandom.Text) % 9 * 9)));
The method Zero returns a string with 0, times the number specified in. I.e Zero(1) would return: "0"
I need this method because the method Next(Int32) can return a number, up to what specified between the brackets. I.e Next(10) would return a number between 0 and 9.
My goal
I want to generate a number with a number of digit above 9, and put the number into the string numToSend. I cannot simply do this, because the method Next() can only generate ints.
Even after your edit, I don't find the question very clear. However, I do think I understand that you are essentially trying to generate a random BigInteger value, and that you want the random value to be within a range defined by some specific number of digits.
For example, if you ask for a 10-digit value, some value between 0 and 9999999999 should be returned. If you ask for a 20-digit value, some value between 0 and 99999999999999999999 should be returned.
Based on that understanding, I believe this method should accomplish what you are asking:
BigInteger NextRandom(Random random, int digitCount)
{
BigInteger result = 0;
while (digitCount-- > 0)
{
result = result * 10 + random.Next(10);
}
return result;
}
Note that the number returned could have fewer than digitCount actual digits in it. In fact, there's always a 1-in-10 chance of that happening. And a 1-in-100 chance of the result having fewer than (digitCount - 1) digits, etc.
If you want something different from that, please be more specific about the exact requirements of the output you want (read https://stackoverflow.com/help/how-to-ask for advice on how to present your question in a clear, answerable way).
For example, the above won't generate a random value within some arbitrary range; the (exclusive) max value can only ever be a power of 10. Also, due to the way BigInteger works, if you are looking for a value with a specific number of binary digits, you can do that simply by using the Random.NextBytes() method, passing the resulting array (making modifications as appropriate to ensure e.g. positive values).
See also C# A random BigInt generator for more inspiration (I would've voted as that for a duplicate, but it seems from your description that you might be looking for a slightly different result than what's requested in that question).

Obsfucate a 5 digit number

I wish to obfuscate a 5 digit number
Properties of the obfuscated number that I care about:
it's impossible (or as a fall back, extremely unlikely) to collide with other obfuscated numbers
it's also a 5 digit number (no alpha characters please)
it's not easily determinable by a regular human without computational assistance (e.g. it's not something obvious like "multiply by 2 and subtract 5"
it's an algorithm ... as opposed to storing a look up table of all possible 5 digit numbers to their corresponding hash or some other "brute force" technique
Properties of the obfuscated number that I don't care about:
whether it's repeatable or not i.e. if "12345" always results in "73624", I okay
whether it's cryptographically secure or not
Thus far I haven't found anything that fits my requirements... but am hoping this is due to poor memory, incomplete education or dubious lifestyle choices rather than no "nice" solution being present.
An example that can be easily translated into C# would be a bonus.
Update:
I'm investigating using the idea of doing a simple bit mapping for the moment.
static List<int> bitMapping = new List<int>() { 8, 6, 9, 3, 7, 5, ... etc... };
private static int Obfuscate(int number)
{
var bits = new bool[bitMapping.Count];
foreach (var ordinal in bitMapping)
{
var mask = (int)Math.Pow(2, ordinal);
var bit = (mask & number) == mask;
var mappedOrdinal = bitMapping[ordinal];
bits[mappedOrdinal] = bit;
}
var obfuscatedNumber = 0;
for (var ordinal = 0; ordinal < bits.Length; ordinal++)
{
if (bits[ordinal])
{
obfuscatedNumber += (int)Math.Pow(2, ordinal);
}
}
return obfuscatedNumber;
It seems to meet most of my requirements thus far.
That might be too simple for your needs, but something that works and might not be as obvious as an addition is the XOR operation :
12345 ^ 65535 = 53190
53190 ^ 65535 = 12345
As noted in comments it is important that the second operand is of the form (2n - 1) to avoid collisions (so that every bit in the original number is inverted). It also needs to be long enough that its number of bits is greater or equal than the first operand.
You might also have to pad-left with 0's to make the result a 5-digit number.
If you don't want collisions then multiplication/division are out. In which case then I would
Add a 5 digit seed value to your number, if it overflows into six digits discard the sixth.
Reorder the digits in some consistent way.
E.g.
12345 + 97531 = 109876 or 09876 after discard overflow
Reorder to 68097

How to remove a number from another number using bitwise operators?

How do I remove for example 2 from 123 and returns 13, by using bitwise operators? I have no idea how to do this.. it's possible? Thanks in advance.
What you're suggesting is possible, but wouldn't really make sense to do. Below are the values representations in bits (only showing relevant bits, everything further left is a zero):
2: 000010 || 123: 1111011 || 13: 001101
There's no logical way to change 123 into 13 with bitwise operations. It would better to turn it into a string or character array, remove the two then cast it back to an int.
What other cases are there? It may be possible to generalize this at an integer level if there is some sort of pattern, otherwise you're really just looking at string replacement.
The 2 in 123 is actually 2E1 (10100), and the 2 in 1234 would be 2E2 (11001000) neither of which are related to 2 (10), at least in bitwise form. Also, the "number" on the right side of the removed number would need to be added to the number on the left side of the removed number / 10.
i.e, to go from 123 to 13:
Located "2".
Number on left (x): 100
Number on right (y): 3
y + (x / 10) = 13
and to go from 1324 to 134
Located "2"
Number on left (x): 1300
Number on right (y): 4
y + (x / 10) = 134
Unless there's some pattern (i.e you know what positions the numbers are in), you'll just have to .ToString() the number, then do a .Replace("2", ""), before doing an int.Parse() on the result.
EDIT: Someone upvoted this answer and I realised my previous implementation was unnecessarily complicated. It is relatively straightforward to 'iterate' over the digits in a base-10 number and shouldn't require recursion.
New solution below, performance is better but this is a huge micro-optimisation:
static int OmitDigit(int number, int digit) {
var output = 0;
var multiplier = 1;
while (number > 0) {
var n = number % 10;
number /= 10;
if (n != digit) {
output += (n * multiplier);
multiplier *= 10;
}
}
return output;
}
Result:
1554443
Since we're working with base 10 numbers, manipulation in base 2 is ugly to say the least. Using some math, removing the nth digit from k, and shifting over is
(k/pow(10,n))*pow(10, n-1) + k%pow(10, n-1)
In base 2, the << and >> operator acts like multiplying by a pow(2, n), and & with a mask does the work of %, but in base 10 the bits don't line up.
This is very awkward, but if you really do must have bitwise operations only, I suggest you convert the number to BCD. Once in BCD, you basically have an hexadecimal numbers with digits between 0 and 9, so removing a digit is very simple. Once you're done, convert back to binary.
I don't believe anybody would want to do that.

Fast way to manually mod a number

I need to be able to calculate (a^b) % c for very large values of a and b (which individually are pushing limit and which cause overflow errors when you try to calculate a^b). For small enough numbers, using the identity (a^b)%c = (a%c)^b%c works, but if c is too large this doesn't really help. I wrote a loop to do the mod operation manually, one a at a time:
private static long no_Overflow_Mod(ulong num_base, ulong num_exponent, ulong mod)
{
long answer = 1;
for (int x = 0; x < num_exponent; x++)
{
answer = (answer * num_base) % mod;
}
return answer;
}
but this takes a very long time. Is there any simple and fast way to do this operation without actually having to take a to the power of b AND without using time-consuming loops? If all else fails, I can make a bool array to represent a huge data type and figure out how to do this with bitwise operators, but there has to be a better way.
I guess you are looking for : http://en.wikipedia.org/wiki/Montgomery_reduction
or the simpler way based on Modular Exponentiation (from wikipedia)
Bignum modpow(Bignum base, Bignum exponent, Bignum modulus) {
Bignum result = 1;
while (exponent > 0) {
if ((exponent & 1) == 1) {
// multiply in this bit's contribution while using modulus to keep result small
result = (result * base) % modulus;
}
// move to the next bit of the exponent, square (and mod) the base accordingly
exponent >>= 1;
base = (base * base) % modulus;
}
return result;
}
Fast Modular Exponentiation (I think that's what it's called) might work.
Given a, b, c and a^b (mod c):
1. Write b as a sum of powers of 2. (If b=72, this is 2^6 + 2^3 )
2. Do:
(1) a^2 (mod c) = a*
(2) (a*)^2 (mod c) = a*
(3) (a*)^2 (mod c) = a*
...
(n) (a*)^2 (mod c) = a*
3. Using the a* from above, multiply the a* for the powers of 2 you identified. For example:
b = 72, use a* at 3 and a* at 6.
a*(3) x a*(6) (mod c)
4. Do the previous step one multiplication at a time and at the end, you'll have a^b % c.
Now, how you're going to do that with data types, I don't know. As long as your datatype can support c^2, i think you'll be fine.
If using strings, just create string versions of add, subtract, and multiply (not too hard). This method should be quick enough doing that. (and you can start step 1 by a mod c so that a is never greater than c).
EDIT: Oh look, a wiki page on Modular Exponentiation.
Here's an example of Fast Modular Exponentiation (suggested in one of the earlier answers) in java. Shouldn't be too hard to convert that to C#
http://www.math.umn.edu/~garrett/crypto/a01/FastPow.html
and the source...
http://www.math.umn.edu/~garrett/crypto/a01/FastPow.java
Python has pow(a,b,c) which returns (a**b)%c (only faster), so there must be some clever way to do this. Maybe they just do the identity you mentioned.
I'd recommend checking over the Decimal documentation and seeing if it meets your requirements since it is a built in type and can use the mod operator. If not then you're going to need an arbitrary precision library like java's Bignum.
You can try factoring 'a' into sufficiently small numbers.
If the factors of 'a' are 'x', 'y', and 'z', then
a^b = (x^b)(y^b)(z^b).
Then you can use your identity: (a^b)%c = (a%c)^b%c
It seems to me like there's some kind of relation between power and mod. Power is just repeated multiplication and mod is related to division. We know that multiplication and division are inverses, so through that connection I would assume there's a correlation between power and mod.
For example, take powers of 5:
5 % 4 = 1
25 % 4 = 1
125 % 4 = 1
625 % 4 = 1
...
The pattern is clear that 5 ^ b % 4 = 1 for all values of b.
It's less clear in this situation:
5 % 3 = 2
25 % 3 = 1
125 % 3 = 2
625 % 3 = 1
3125 % 3 = 2
15625 % 3 = 1
78125 % 3 = 2
...
But there's still a pattern.
If you could work out the math behind the patterns, I wouldn't be surprised if you could figure out the value of the mod without doing the actual power.
You could try this:
C#: Doing a modulus (mod) operation on a very large number (> Int64.MaxValue)
http://www.del337ed.com/blog/index.php/2009/02/04/c-doing-a-modulus-mod-operation-on-a-very-large-number-int64maxvalue/
Short of writing your own fast modular exponentiation, the simplest idea I can come up with, is to use the F# BigInt type: Microsoft.FSharp.Math.Types.BigInt which supports operations with arbitrarily large scale - including exponentiation and modular arithmetic.
It's a built-in type that will be part of the full .NET framework with the next release. You don't need to use F# to use BitInt - you can make use of it directly in C#.
Can you factor a, b, or c? Does C have a known range?
These are 32 bit integers! Go check this site
For instance, here is how you get the mod of n%d where d 1>>s (1,2,4,8,...)
int n = 137; // numerator
int d = 32; // denom d will be one of: 1, 2, 4, 8, 16, 32, ...
int m; // m will be n % d
m = n & (d - 1);
There is code for n%d where d is 1>>s - 1 (1, 3, 7, 15, 31, ...)
This is only going to really help if c is small though, like you said.
Looks like homework in cryptography.
Hint: check out Fermat's little theorem.

Categories

Resources