C# - Constantly adding 9 digits - c#

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).

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 sharp finding a specific digit in an int [duplicate]

This question already has answers here:
Get the seventh digit from an integer
(9 answers)
Get individual digits from an Int without using strings?
(1 answer)
Closed 4 years ago.
I'm trying to find the nth digit of an integer (from right to left). I'm new to programming but have been using this site a lot for reference - up until now I've resisted passing my problems on but I cannot understand this one in the least, even after hours of effort.
This is the code I have so far but for FindDigit(int 5673, int 4) it gives 53 instead of 5, FindDigit(int 5673, int 3) gives 51 instead of 6
public class DigitFinder
{
public static int FindDigit(int num, int nth)
{
num = Math.Abs(num);
string answer = Convert.ToString(num);
int i = answer.Length;
return ans[i-nth];
}
}
I cannot understand at all why it returns a 2 digit number. Any guidance at all appreciated!
I'd just use
int result = (num / (int)Math.Pow(10,nth-1)) % 10;
Where num is the number to get the nth digit from (counted right to left) and nth is the "index" of digits you want (again: counted from right to left). Mind that it is 1-based. That is "1" is the rightmost digit. "0" would be out of range.
To explain the math:
(int)Math.Pow(10,nth-1) takes your desired index and decreases it by 1, then takes that as the power of 10. So if you want the 3rd digit, that makes 10 to the power of two equals 100.
BTW: the cast to int is necessary because Math.Pow works on double and returns double. But we want to keep on working in integer arithmetic.
Dividing by the result of above equation "shifts" your number to the right, so your desired digit becomes the rightmost digit. Example: 1234, we want 3rd digit from right ("2") => 1234 / (10^(3-1))= 1234 / 100 = 12
You then "cut out" that rightmost digit by applying the "remainder" (modulo) operator with divisor 10. Example: 12 % 10 = [12 / 10 = 1, Remainder =] 2.
Mind that I also would check nth to be > 0 and num >= 10 ^ (nth-1). (never trust user input)
53 is the ASCII code of the character 5. Just subtract the character 0, i.e. numeric 48.
However, it is usually a good idea to avoid string manipulation for things like this; if possible you should probably prefer division/remainder (modulo) arithmetic.
Just because no one else did, and also because i have Printable Character OCD
public static int GetLeastSignificantDigit(int number, int digit)
{
for (var i = 0; i < digit - 1; i++)
number /= 10;
return number % 10;
}
Demo here

C# formula to determine index

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).

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.

Project euler number 10#

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
And my answer is:
bool IsRishoni;
int soap = 0;
for (int i = 3; i < 2000000; i++)
{
IsRishoni = true;
for (int a = 2; (a <= Math.Sqrt(i)) && (IsRishoni); a++)
{
if (i % a == 0)
IsRishoni = false;
}
if (IsRishoni)
{
soap = i + soap;
}
}
Console.WriteLine(soap + 2);
Console.ReadLine();
Why is this not working? the answer I got is 1179908154 ... help please.
Replace
soap = i + soap;
with
soap = checked(i + soap);
..and the problem should be exposed.
This question has more details: No overflow exception for int in C#?
Your answer (stored in soap) is a value greater than int.Maxvalue (2,147,483,647).
Your answer is ~ 150,000,000,000
In other words you need to use an data type which is bigger than that.
long.MaxValue = 9,223,372,036,854,775,807
int.Maxvalue = 2,147,483,647
The result you’re after might be too large to represent through a 32-bit signed integer (int).
Let’s first determine the result’s upper bound by assuming that all numbers are prime. Through summation, we know that the sum of all numbers up to N (inclusive) is N * (N + 1) / 2; thus, the upper bound for the sum of all primes up to 2,000,000 is 2,000,001,000,000. This is larger than the maximum value allowed by int, 2,147,483,647, so you’re probably getting a numeric overflow which is silently ignored.
If you wanted a more accurate estimate of your answer, you could use the prime number theorem, which states that the probability of a random integer between 0 and N being prime is approximately 1 / ln(N). Combining this with our previous formula, the approximate sum of all primes up to N is N * (N + 1) / (2 * ln(N)). For 2,000,000, this evaluates to around 138,000,000,000, which is still larger than the maximum value for int.
To resolve your problem, you could simply switch the integral data type you’re using for the soap variable to a 64-bit integer representation, such as long. Its maximum value is 9,223,372,036,854,775,807, so it would definitely be able to represent your number.
long soap = 0;
On a separate note: Since you’re working with sequences of primes, you could achieve a huge performance gain (at least 100×) if you change your implementation to a Sieve of Eratosthenes.

Categories

Resources