Cycle through int values - c#

I need some input.
Say you have an int-based Enum with values 1 through 10. If you then have a variable that is, say, value corresponding to 7, how can you easiest set it to next value in the given range without going out of bounds? If the value reaches the limit, it should reset itself to first in the range.
I want a one-liner solution to this. I don't want to do ++ and then check and reset value, plus it has to work in both C# and JavaScript. I suppose something in the Math object might be of help, I don't know...
thanks

Increment, subtract 1, then modulo, then add 1 (since your Enum is 1-based).
((++i - 1) % N + 1
(N=10, the maximum value your Enum can take on.)

If you know the limits and are sure that all numbers between 0 and that upper limit is occupied by an enum you can use the modulo operator
myEnum = (myEnum + 1) % maxValue;
You may need to typecast:
myEnum = (MyEnumType) (((int) myEnum + 1) % maxValue);
EDIT: I noticed you have one-based enums. If you really need this, then you would have to do as larsman suggests in his answer:
// This statement may look weird, but it works :)
myEnum = (myEnum % maxValue) + 1
// Produces (for myEnum with maxValue set to 4, i.e. allows 1,2,3 & 4 as valid values):
// 1 => 2
// 2 => 3
// 3 => 4
// 4 => 1

Related

Get the sign of a number in C# without conditional statement

Just out of curiosity, is there a way to get the sign of a number, any kind (but obviously a signed type), not just integer using some bitwise/masking, or other kind of, operation?
That is without using any conditional statement or calling the Math.Sign() function.
Thanks in advance!
EDIT: I recognize it was a misleading question. What I had in mind more likely something like: "get the same output of the Math.Sign() or, simplifying get 0 if x <= 0, 1 otherwise".
EDIT #2: to all those asking for code, I didn't have any in mind when I posted the question, but here's an example I came up with, just to give a context of a possible application:
x = (x < 0) ? 0 : x;
Having the sign into a variable could lead to:
x = sign * x; //where sign = 0 for x <= 0, otherwise sign = 1;
The aim would be to achieve the same result as the above :)
EDIT #3: FOUND IT! :D
// THIS IS NOT MEANT TO BE PLAIN C#!
// Returns 0 if x <= 0, 1 otherwise.
int SignOf(x)
{
return (1+x-(x+1)%x)/x;
}
Thanks to everyone!
is there a way to get the sign of a number (any kind, not just integer)
Not for any number type, no. For an integer, you can test the most significant bit: if it's 1, the number is negative. You could theoretically do the same with a floating point number, but bitwise operators don't work on float or double.
Here's a "zero safe" solution that works for all value types (int, float, double, decimal...etc):
(value.GetHashCode() >> 31) + 1;
Output: 1 = 1, -1 = 0, 0.5 = 1, -0.5 = 0, 0 = 1
It's also roughly 10% cheaper than (1+x-(x+1)%x)/x; in C#. Additionally if "value" is an integer, you can drop the GetHashCode() function call in which case (1+x-(x+1)%x)/x; is 127% more expensive ((value >> 31) + 1; is 56% cheaper).
Since 0 is positive it is illogical for a result of 1 for positive numbers & a result of 0 for 0. If you could parametrise -0 you would get an output of 0.
I understand that GetHashCode() is a function call, but the inner workings of the function in the C# language implementation is entirely "arithmetic". Basically the GetHashCode() function reads the memory section, that stores your float type, as an integer type:
*((int*)&singleValue);
How the GetHashCode function works (best source I could find quickly) - https://social.msdn.microsoft.com/Forums/vstudio/en-US/3c3fde60-1b4a-449f-afdc-fe5bba8fece3/hash-code-of-floats?forum=netfxbcl
If you want the output value to be 1 with the same sign as the input, use:
((float.GetHashCode() >> 31) * 2) + 1;
The above floating-point method is roughly 39% cheaper than System.Math.Sign(float) (System.Math.Sign(float) is roughly 65% more expensive). Where System.Math.Sign(float) throws an exception for float.NaN, ((float.NaN.GetHashCode() >> 31) * 2) + 1; does not and will return -1 instead of crashing.
or for integers:
((int >> 31) * 2) + 1;
The above integer method is roughly 56% cheaper than System.Math.Sign(int) (System.Math.Sign(int) is roughly 125% more expensive).
It depends on the type of number value type you are targeting.
For signed Integers C# and most computer systems use the so called Ones' complement representation.
That means the sign is stored in the first bit of the value.
So you can extract the sign like this:
Int16 number = -2;
Int16 sign = (number & Int16.MinValue) >> 16;
Boolean isNegative = Convert.ToBoolean(sign);
Note that up until now we have not used any conditional operator (explicitly anyways)
But: You still don't know whether the number has a sign or not.
The logical equivalent of your question: "How do I know, if my number is negative?" explicitly requires the usage of a conditional operator as the question is, after all conditional.
So you won't be able to dodge:
if(isNegative)
doThis();
else
doThat();
to just get the sign, you can avoid conditional operators as you will see below in Sign extension of int32 struct. however to get the name I dont think you can avoid conditional operator
class Program
{
static void Main(string[] args)
{
Console.WriteLine(0.Sign());
Console.WriteLine(0.SignName());
Console.WriteLine(12.Sign());
Console.WriteLine(12.SignName());
Console.WriteLine((-15).Sign());
Console.WriteLine((-15).SignName());
Console.ReadLine();
}
}
public static class extensions
{
public static string Sign(this int signedNumber)
{
return (signedNumber.ToString("+00;-00").Substring(0, 1));
}
public static string SignName(this int signedNumber)
{
return (signedNumber.ToString("+00;-00").Substring(0, 1)=="+"?"positive":"negative");
}
}
if x==0 you will have a divby0 exception with this code you posted:
int SignOf(x) {
return (1+x-(x+1)%x)/x; }

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

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.

How to convert number to next higher multiple of five?

I am coding a program where a form opens for a certain period of time before closing. I am giving the users to specify the time in seconds. But i'd like this to be in mutliples of five. Or the number gets rounded off to the nearest multiple.
if they enter 1 - 4, then the value is automatically set to 5.
If they enter 6 - 10 then the value is automatically set to 10.
max value is 60, min is 0.
what i have, but i am not happy with this logic since it resets it to 10 seconds.
if (Convert.ToInt32(maskedTextBox1.Text) >= 60 || Convert.ToInt32(maskedTextBox1.Text) <= 0)
mySettings.ToastFormTimer = 10000;
else
mySettings.ToastFormTimer = Convert.ToInt32 (maskedTextBox1.Text) * 1000;
use the Modulus Operator
if(num % 5 == 0)
{
// the number is a multiple of 5.
}
what about this:
int x = int.Parse(maskedTextBox1.Text)/5;
int y = Math.Min(Math.Max(x,1),12)*5; // between [5,60]
// use y as the answer you need
5 * ((num - 1) / 5 + 1)
Should work if c# does integer division.
For the higher goal of rounding to the upper multiple of 5, you don't need to test whether a number is a multiple. Generally speaking, you can round-up or round-to-nearest by adding a constant, then rounding down. To round up, the constant is one less than n. Rounding an integer down to a multiple of n is simple: divide by n and multiply the result by n. Here's a case where rounding error works in your favor.
int ceil_n(int x, int n) {
return ((x+n-1) / n) * n;
}
In dynamic languages that cast the result of integer division to prevent rounding error (which doesn't include C#), you'd need to cast the quotient back to an integer.
Dividing by n can be viewed as a right-shift by 1 place in base n; similarly, multiplying by n is equivalent to a left-shift by 1. This is why the above approach works: it sets the least-significant digit of the number in base n to 0.
2410=445, 2510=505, 2610=515
((445+4 = 535) >>5 1) <<5 1 = 505 = 2510
((505+4 = 545) >>5 1) <<5 1 = 505 = 2510
((515+4 = 605) >>5 1) <<5 1 = 605 = 3010
Another way of zeroing the LSD is to subtract the remainder to set the least significant base n digit to 0, as Jeras does in his comment.
int ceil_n(int x, int n) {
x += n-1;
return x - x%n;
}

Categories

Resources