strange behavior of integers - c#

I have the following code
int a = 1, n = 1;
Convert.ToInt32(a = a++ + n--);
Console.WriteLine("a: " + a + " n : " + n);
//If you debug the second line of the code in quick watch the answer is 3.
The answer to above code should be 2, so it is. But if i debug it and see the value in quickwatch the value of a is printed 3. Any idea why the same code results two different values.

Also note that the increment/decrement operators tailing the variables will be executed after the variable is used in the calculation (but before the result is written into a).
This will be interpreted as a= 1 +1, not a = 2 + 0
Specifcally the programm flows:
Take 1 out of 'a' into calculation memory.
Increment 'a' by 1
take 1 out of 'n' into calculation memory
Decrement 'n' by 1
Set 'a' to the sum of the two values you extracted earlier (not the current values of those variables)
Often putting seperate steps into seperate lines can yield a lot better debugging. i.e.:

Related

What's the proper way to generate 6 characters alphanumeric code in which sum of all characters equals 9? (Voucher code generator)

My first idea was to make an array/list that has values assigned to each character.
So for example:
array[0] =' 0'
array[10] = 'A'
[...]
Then code would pick a random number y between [0,x] for slot 1.
For next slot [0,(x-y)] etc. When y <= 0 then fill rest of the slots with '0'.
Would that be enough for a simple voucher code generator? (It's not my decision to make encryption with this rule)
I am worried that sum of 9 is quite low for 6 character code, letters won't be used at all since they all have value over 9.
To prevent situation like this:
540000, 630000, 180000
Should I make chance of '0' to appear more?
What do you guys think about it?
Maybe you could also suggest some other way of doing this.
#Edit
Examples:
112320 = 1+1+2+3+2+0 = 9 Valid code, sum equals 9
000900 = 0+0+0+9+0+0 = 9 Valid code, sum equals 9
003015 = 0+0+3+0+1+5 = 9 Valid code, sum equals 9
A0012B = 10+0+0+1+2+11 = 24 Invalid code
Let's say that the function Rand(n) creates a random integer number that can go from 0 up to n (n included), then you can do the following:
Sum = 0;
A[0] = Rand(9);
Sum += A[0];
A[1] = Rand(9 - Sum);
Sum += A[1];
A[2] = Rand(9 - Sum);
Sum += A[2];
...
I just wrote this down very quickly, I didn't check the boundaries, but such an algorithm should do the trick.

How to increase value of an integer higher than 1 in one command?

You could write example++; multiple times in your loop if you need to increase by more than 1, but what if i need to increase by like 100? Is there a way to make it multiply or increase by more than 1? (other than multiplying it in Console.WriteLine)
Per the comment from peter:
example += 100;
Means the same as
example = example + 100;
This is called Compound Assignment and there are many operators that do their work in this way, such as
example -= 100;
example *= 100;
For the full list, refer to the MSDN linked above
Any assignment in c# returns the assigned value so it can be used as part of a bigger statement. The += is no different, and this will print "x incremented is 101":
int x = 1;
Console.WriteLine("x incremented is " + (x+= 100));
The only thing worthy of note is that ++ exists in two forms, either x++ or ++x - the first form returns the value of x before it was incremented, the second form returns the value after.
int x = 1;
Console.WriteLine("x incremented is " + (x++)); //x is now 2 but the message says it is 1
Console.WriteLine("x incremented is " + (++x)); //x is now 3 and the message says it is 3
+= only returns the value after increment. There is no form that returns x before you add 100 to it
The simplest solution to increase value of example by an amount x would be example=example+x. This is more legible, however you can use the short form example+=x.

rounding up columns of values

I start with figures in line 1 for columns A nd B, (see below) 890 and 450 and both are divided by 1.2 to get a net figure (line 2), the results of which are then split over two types (say salesA and salesB)
How can I ensure that the sum of salesA + salesB will always be equal to the values shown on line 2 which in turn will be equal to values on line 1 when multiplied by 20%.
As you can see, column B is out by 0.02
Example
column A column B
890.00 /1.2 450.00 /1.2
741.67 375.00
333.33 salesA 208.35 salesA
408.34 salesB 166.67 salesB
741.67 375.02 sum of salesA + sales B
Values on line 2 multiplied by 20% should be equal to values on line 1
How can this be achieved ? I am aware of Math.Round.
Have tried inserting it everywhere but it doesn’t work
The division operator is inside a select statement
You are doing something like this when splitting:
total = 741.67
a = round(f(total), 2)
b = round(g(total), 2)
where f() and g() are the calculations used to split. Instead do this:
total = 741.67
a = round(f(total), 2)
b = total - a;
Now a + b are always equal to total.
However, you will never be able to get the starting value again when multiplying with 1.2 because of the rounding.

How string quote, length total count and arrayname[int] work?

I'm making a program which reverses words to sdrow.
I understand that for it to work it needs to be written this way.
I'm more interested on WHY it has to be this way.
Here is my code:
Console.WriteLine("Enter a word : ");
string word = Console.ReadLine();
string rev = "";
int length;
for (length = word.Length - 1; length >= 0; length--)
{
rev = rev + word[length];
}
Console.WriteLine("The reversed word is : {0}", rev);
My questions are:
a) why you must use quotes to initialize your string
b) Why must you start your loop at one less than the total length of your string
c) How arrayname[int] works
I'm pretty new to C# and this site, as well. I hope my questions make sense and that I've asked them in the correct and proper way.
Thank you for your time!
This is how I've interpreted your question.
You want to know why you must use quotes to initialize your string
Why must you start your loop at one less than the total length of your string
How arrayname[int] works
I think that the best way to explain this to you is to go through your code, and explain what it does.
Console.WriteLine("Enter a word : ");
The first line of code prints Enter a word : into the console.
string word = Console.ReadLine();
This line "reads" the input from the console, and puts it into a string called word.
string rev = "";
This initiates a string called rev, setting it's value to "", or an empty string. The other way to initiate the string would be this:
string rev;
That would initiate a string called rev to the value of null. This does not work for your program because rev = rev + word[length]; sets rev to itself + word[length]. It throws an error if it is null.
The next line of your code is:
int length;
That sets an int (which in real life we call an integer, basically a number) to the value of null. That is okay, because it gets set later on without referencing itself.
The next line is a for loop:
for (length = word.Length - 1; length >= 0; length--)
This loop sets an internal variable called length to the current value of word.Length -1. The second item tells how long to run the loop. While the value of length is more than, or equal to 0, the loop will continue to run. The third item generally sets the rate of increase or decrease of your variable. In this case, it is length-- that decreases length by one each time the loop runs.
The next relevant line of code is his:
rev = rev + word[length];
This, as I said before sets rev as itself + the string word at the index of length, whatever number that is at the time.
At the first run through the for loop, rev is set to itself (an empty string), plus the word at the index of length - 1. If the word entered was come (for example), the index 0 would be c, the index 1 would be o, 2 would be m, and 3 = e.
The word length is 4, so that minus one is 3 (yay - back to Kindergarten), which is the last letter in the word.
The second time through the loop, length will be 2, so rev will be itself (e) plus index 2, which is m. This repeats until length hits -1, at which point the loop does not run, and you go on to the next line of code.
...Which is:
Console.WriteLine("The reversed word is : {0}", rev);
This prints a line to the console, saying The reversed word is : <insert value of rev here> The {0} is an internal var set by the stuff after the comma, which in this case would be rev.
The final output of the program, if you inserted come, would look something like this:
>Enter a word :
>come
>
>The reversed word is : emoc
a) you must to initialize or instantiate the variable in order to can work with it. In your case is better to use and StringBuilder, the string are inmutable objects, so each assignement means to recreate a new string.
b) The arrays in C# are zero index based so their indexes go from zero to length -1.
c) An string is an characters array.
Any case maybe you must to try the StringBuilder, it is pretty easy to use
I hope this helps
a) you need to initialize a variable if you want to use it in an assignment rev = rev + word[length];
b) you are using a for loop which means that you define a start number length = word.Length - 1, a stop criteria length >= 0 and a variable change length--
So lenght basically descends from 5 to 0 (makes 6 loops). The reason is that Arrays like 'string' a char[] are zerobased indexed.. means that first element is 0 last is array.Length - 1
c) So a string is basically a chain of char's.. with the []-Operator you can access a single index. The Return Type of words[index] is in this case a character.
I hope it helped
a) You need to first instantiate the string rev before you can assign it values in the loop. You could also say "string rev = String.Empty". You are trying to add word to rev and if you don't tell it first that rev is an empty string it doesn't know what it is adding word to.
b) The characters of the string have indexes to show which position they appear in the string. These indexes start at 0. So you're first character will have an index of 0. If the length of your string is 6 then the last character's index will be 5. So length - 1 will give you the value of the last character's index which is 5. A c# for loop uses the following parameters
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
where "int i = 0;" is the starting index; "i < 10" tells the loop when to stop looping; and "i++" tells it to increment i (the index) after each loop.
So in your code you are saying start at the last character of my string; perform this loop while there are still characters in the string; and decrease the index of the string after each loop so the next loop will look at the previous character in the string.
c) word[length] then in this scenario is saying add the character that has the position with index "length" to the rev string. This will basically reverse the word.
As usual you can do it in linq and avoid the (explicit) loops
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Enter a word : ");
string word = Console.ReadLine();
Console.WriteLine("The reversed word is : {0}", new string (word.Reverse().ToArray()));
Console.ReadLine();
}
}
}
var reversedWords = string.Join(" ",
str.Split(' ')
.Select(x => new String(x.Reverse().ToArray())));
Take a look here :
Easy way to reverse each word in a sentence

int[] arr={0}; int value = arr[arr[0]++]; Value = 1?

Today I came a cross an article by Eric Lippert where he was trying to clear the myth between the operators precedence and the order of evaluation. At the end there were two code snippets that got me confused, here is the first snippet:
int[] arr = {0};
int value = arr[arr[0]++];
Now when I think about the value of the variable value, I simply calculate it to be one. Here's how I thought it's working.
First declare arr as an array of int
with one item inside of it; this
item's value is 0.
Second get the value of arr[0] --0 in
this case.
Third get the value of arr[the value
of step 2] (which is still 0) --gets
arr[0] again --still 0.
Fourth assign the value of step 3
(0) to the variable value. --value =
0 now
Add to the value of step 2 1 --Now
arr[0] = 1.
Apparently this is wrong. I tried to search the c# specs for some explicit statement about when the increment is actually happening, but didn't find any.
The second snippet is from a comment of Eric's blog post on the topic:
int[] data = { 11, 22, 33 };
int i = 1;
data[i++] = data[i] + 5;
Now here's how I think this program will execute --after declaring the array and assigning 1 to i. [plz bear with me]
Get data[i] --1
Add to the value of step 1 the value
5 --6
Assign to data[i] (which is still 1)
the value of step 2 --data[i] = 6
Increment i -- i = 2
According to my understanding, this array now should contain the values {11, 27, 33}. However, when I looped to print the array values I got: {11, 38, 33}. This means that the post increment happened before dereferencing the array!
How come? Isn't this post increment supposed to be post? i.e. happen after everything else. What am I missing guys?
The postincrement operation occurs as part of evaluating the overall expression. It's a side effect which occurs after the value is evaluated but before any other expressions are evaluated.
In other words, for any expression E, E++ (if legal) represents something like (pseudo-code):
T tmp = E;
E += 1;
return tmp;
That's all part of evaluating E++, before anything else is evaluated.
See section 7.5.9 of the C# 3.0 spec for more details.
Additionally, for assignment operations where the LHS is classified as a variable (as in this case), the LHS is evaluated before the RHS is evaluated.
So in your example:
int[] data = { 11, 22, 33 };
int i = 1;
data[i++] = data[i] + 5;
is equivalent to:
int[] data = { 11, 22, 33 };
int i = 1;
// Work out what the LHS is going to mean...
int index = i;
i++;
// We're going to assign to data[index], i.e. data[1]. Now i=2.
// Now evaluate the RHS
int rhs = data[i] + 5; // rhs = data[2] + 5 == 38
// Now assign:
data[index] = rhs;
The relevant bit of the specification for this is section 7.16.1 (C# 3.0 spec).
For the first snippet, the sequence is:
Declare arr as you described:
Retrieve the value of arr[0], which is 0
Increment the value of arr[0] to 1.
Retrieve the value of arr[(result of #2)] which is arr[0], which (per #3) is 1.
Store that result in value.
value = 1
For the second snippet, the evaluation is still left-to-right.
Where are we storing the result? In data[i++], which is data[1], but now i = 2
What are we adding? data[i] + 5, which is now data[2] + 5, which is 38.
The missing piece is that "post" doesn't mean "after EVERYTHING else." It just means "immediately after I retrieve the current value of that variable." A post increment happening "in the middle of" a line of code is completely normal.
data[i++] // => data[1], then i is incremented to 2
data[1] = data[2] + 5 // => 33 + 5
I would expect the post-increment operator to increment the variable after its value is used.
In this case, the variable is incremented before the second reference to the variable.
If it would not be so, you could write
data[i++] = data[i++] + data[i++] + data[i++] + 5
If it would be like you say, then you could remove the increment operator because it doesn't do actually anything, in the instruction I reported.
You have to think of assignments in three steps:
Evaluate left hand side (=get address where the value should be stored)
Evaluate right hand side
Assign the value from step 2 to the memory location from step 1.
If you have something like
A().B = C()
Then A() will run first, then C() will run, and then the property setter B will run.
Essentially, you have to think of your statement as
StoreInArray(data, i++, data[i] + 5);
The cause might be that some compilers optimize i++ to be ++i. Most of the time, the end result is the same, but it seems to me to be one of those rare occasions when the compiler is wrong.
I have no access to Visual Studio right now to confirm this, but try disabling code optimization and see if the results will stay the same.

Categories