If statement in Calculator - c#

I'm a beginner programmer designing a calculator in Visual Studio 2013 using C#. I've run into a slight problem that I can't seem to fix. When I click on the square root button, I want the program to display the square root in the text box, as well as show what's happening in the label.
For example, if I want to calculate 9 + sqrt(16), I need to click 9 + 16, then press the square root button. The label above the text box should show "9 + sqrt(16)" and the text box itself should say "4". This all works like it should. But if I then take the square root of 4, I want the label to say "9 + sqrt(4)". I tried storing the first part (9 + ) as a string, but when the square root button is pressed twice, it displays "9 + sqrt(16) sqrt(4)".
Is there a different way to fix this or am I doing something wrong?
Here's part of the code I tried (result is the text box and expression is the label):
private void sqrt_Click(object sender, EventArgs e)
{
bool square_root_pressed = false;
string exp = "";
Button b = (Button)sender;
double res = Convert.ToDouble(result.Text);
if ((equal_pressed) || (operation == ""))
{
if (b.Text == "√")
{
result.Text = Convert.ToString(Math.Sqrt(res));
expression.Text = "sqrt(" + Convert.ToString(res) + ") =";
}
else
{
result.Text = Convert.ToString(Math.Sqrt(res));
if (square_root_pressed)
{
expression.Text = exp + " sqrt(" + Convert.ToString(res) + ")";
}
else
{
exp = expression.Text;
expression.Text = expression.Text + " sqrt(" + Convert.ToString(res) + ")";
square_root_pressed = true;
}
}

the local variable square_root_pressed is always set to false when the event handler is called. The statement
expression.Text = exp + " sqrt(" + Convert.ToString(res) + ")";
will never be reached.
Try to store the state of keys pressed outside of the event handler.

you can add another event handler for "square root" and double the number when the Event is called,
once you click on the sqrt_Click Event "res" calculated the correct sqrt number.

If i understand your question properly, when the square root button is pressed twice, the label display repeats sqrt. A possible solution is when the statement exp = expression.Text executes; check to see if the text sqrt already exists in the label. If so then remove it in-order to avoid duplication.
exp = expression.Text;
if (exp.Contains("sqrt"))
{ exp = exp.Remove(exp.IndexOf("sqrt")); }
expression.Text = exp + " sqrt(" + Convert.ToString(res) + ")";
square_root_pressed = true;

I would suggest a totally different approach: I'd store the entire term as a list of objects and write a method to visualize them.
An example for what I mean could be the following:
public class Operation
{
public string Operator;
}
public class Function
{
public string Functor;
public List<object> Term;
}
These two classes would be my little helpers. Now if the user presses only numbers and operators, you can fill a list of term items like this:
public List<object> term = new List<object>();
...
term.Add(3);
term.Add(new Operation() { Operator = "+" });
term.Add(4);
This would be the equivalent of 3+4.
If the user presses the SQRT button, you could do this:
// Get the last element in the term and remove it
object o = term[term.Count - 1];
term.RemoveAt(term.Count - 1);
// Wrap the element in a function
Function f = new Function() { Functor = "SQRT" };
f.Term = new List<object>();
f.Term.Add(o);
// Add the function as new element to the term
term.Add(f);
This would turn the list from
3
+
4
into
3
+
SQRT
4
Similarly, if the user presses SQRT again, you can remove the function:
// Get the last element in the term and remove it
object o = term[term.Count - 1];
term.RemoveAt(term.Count - 1);
// Add the function term as new element to the term
term.AddRange((o as Function).Term);

Related

I have multiple text boxes (tbVarName1, tbVarName2, ... tbVarName[n]) and I want to increment them in a for loop to assign the text to something

I have a multiple text boxes that I want to assign their string content to a variable however I'm not sure how to increment the text boxes. They are named, tbVarName1, tbVarname2, et cetera. Below is the for loop I have, right now I just have tbVarName1 hard coded in.
I have researched some of what other people have done and have only found tips for doing it in VB.
for(seriesIndex = 1; seriesIndex <= 4; seriesIndex++)
{
dataChart.Series["Variable " + seriesIndex].LegendText = tbVarName1.Text
}
At the end of this I would like the the legends to be updated to what's in the text boxes
Another way to do it is using the Controls collection from the Form (assuming that all TextBoxes are direct children of the form)
var ctrl = this.Controls.OfType<TextBox>();
for(seriesIndex = 1; seriesIndex <= 4; seriesIndex++)
{
TextBox t = ctrl.FirstOrDefault(c => c.Name == "tbVarName" + i);
if(t != null) dataChart.Series["Variable " + seriesIndex].LegendText = t.Text;
}
This will not require an array but you could end with a bigger loop if you have many controls of type textbox and it is not worth the effort if the TextBox are children of different containers (panels, groupboxes)
There are various ways to do this, one way is to add the controls into an array, for example:
var controls = new [] { tbVarName1, tbVarName2, tbVarName3 };
And now you can access them by index:
for(seriesIndex = 1; seriesIndex <= 4; seriesIndex++)
{
dataChart.Series["Variable " + seriesIndex].LegendText = controls[seriesIndex - 1].Text;
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// Like this
// Note: arrays start at zero
}

CNTK Sequences in C#

I made a working script in python to train a CNTK Model with some data samples. Now I'm trying to translate it to C# in CNTK V2.2 but I'm getting different results.
This is what I got in Python to create a model:
def create_model_function(num_hidden_layers,hidden_layers_dim,num_output_classes):
return Sequential([For(range(num_hidden_layers)
, lambda i: Dense(hidden_layers_dim
, activation=cntk.tanh))
, Dense(num_classes,init=cntk.glorot_uniform()
, activation=cntk.softmax)])
Thanks
My C# function looks like this:
private Function CreateModel(DeviceDescriptor device, int HiddenLayerCount, int HiddenLayerDimension,int OutputClassesCount, Variable Input)
{
Function[] HiddenLayers= new Function[HiddenLayerCount];
for (int i = 1; i < HiddenLayerCount - 1; i++)
{
HiddenLayers[i] = Dense(HiddenLayers[i - 1], HiddenLayerDimension, device, Activation.Tanh, "");
}
return Dense(HiddenLayers[HiddenLayerCount-1], OutputClassesCount, device, Activation.Sigmoid, "");
}
I'm just not sure this is the equivalent of the Python sequential.
Python Dense function is not directly supported in C# yet. The Dense function you used in C# might be different than CNTK Python implementation. May you build a model in both C# and python with operators available in C# and see if they are the same?
I am attaching a C# function to help you check the model graph. Use it with python model loaded into C# and compare with the one you created in C#. Thanks.
static void PrintGraph(Function function, int spaces, bool useName = false)
{
string indent = new string('.', spaces);
if (function.Inputs.Count() == 0)
{
Console.WriteLine(indent + "(" + (useName ? function.Name : function.Uid) + ")" +
"(" + function.OpName + ")" + function.AsString());
return;
}
foreach (var input in function.Inputs)
{
Console.WriteLine(indent + "(" + (useName ? function.Name : function.Uid) + ")" +
"(" + function.OpName + ")" + "->" +
"(" + (useName ? input.Name : input.Uid) + ")" + input.AsString());
}
foreach (var input in function.Inputs)
{
if (input.Owner != null)
{
Function f = input.Owner;
PrintGraph(f, spaces + 4, useName);
}
}
}
Following example shows a simple feed forward path from left to right.
To generate the deep network,
control the FOR LOOP per your requirements.
In this example,
Loop control is modifying number of nodes with even and odd loopcount.
CreateUniteLayer builds a unit layer
- LXNodes on left side connected to LYNodes on right side.
Other variables are self explained.
ParameterVector NetParamVec is needed to create the trainer.
Pass this as parameter if you use CNTKLib.xxxx_learner function.
Carefully check on connectivity of Input features to first layer,
First layer to intermediate layers
and then last layer connection
finally leading to sigmoid.
Adjust LXNodes and LYNodes variables appropriately per your need.
Add this code in a class or pull it inside a method as appropriate for your application.
If building all layers of same node size,
LXNodes = LYNodes = number of nodes per layer
NetOut represents final output of the deep network.
Hope this helps to build the net you are looking for.
Best wishes.
List<Function> Layers = new List<Function>() ;
ParameterVector NetParamVec = new ParameterVector ();
// Define first layer immediately after input.
Function layer1 = CreateUnitLayer(features, LXNodes, inputDim, "NetLayer0", InitWeight, InitBias);
Layers.Add(layer1);
//Defines Intermediate hidden layers
for (int i = 1; i < LayerCount; i++)
{
Function ly;
if (i % 2 == 0)
ly = CreateUnitLayer(Layers[i - 1], LXNodes, LYNodes, "NetLayer" + i.ToString(), InitWeight, InitBias);
else
ly = CreateUnitLayer(Layers[i - 1], LYNodes, LXNodes, "NetLayer" + i.ToString(), InitWeight, InitBias);
Layers.Add(ly);
}
//Defines Last layer
int lastDim = LXNodes;
if (LayerCount % 2 == 0)lastDim = LYNodes;
Function layerLast = CreateUnitLayer(Layers[LayerCount - 1], outDim, lastDim, "NetLayerOut", InitWeight, InitBias);
Layers.Add(layerLast);
Function NetOut = CNTKLib.Sigmoid(layerLast);
public Function CreateUnitLayer(Variable LXIn, int LYNodes, int LXNodes, string LYName, float InitWeight, float InitBias)
{
Parameter weightParamy = new Parameter(new int[] { LYNodes, LXNodes }, DataType.Float, InitWeight, device, "W" + LYName);
Parameter biasParamy = new Parameter(new int[] { LYNodes }, DataType.Float, InitBias, device, "B" + LYName);
Function LayerY = CNTKLib.Plus(CNTKLib.Times(weightParamy, LXIn), biasParamy);
NetParamVec.Add(weightParamy);
NetParamVec.Add(biasParamy);
return LayerY;
}

Issue with printing to list (WPF) and editing information using C#

I am currently a few weeks into a home A level computing course and have hit a bit of a hurdle, I will print the tasks I have but I am having an issue with 4,5 and 6, I am really stuck and can't seem to find any information on how I would go about this online.
Generate a random name: en-da-fu and el-kar-tuk could be names, so you could make a name generator which sticks together three syllables from ‘word
banks’
Create the generic character class. Test to see if you can create multiple characters.
Create subclasses corresponding to different types of creature (B, E, W, D & K).
Make a program that randomly generates 10 of these creatures to add into a list.
Make a method in the character class that enables printing out of each character’s stats to the console.
Create a menu system that lets you add and delete characters and print out the list until you are happy with the team.
Create methods to let you edit any character’s stats and add this to your menu system
Create a way to save your team to a file and load it up again if needed
=======================================================================
code so far, also have a listBox called partySelectionListBox
// This will search for and load the information in NameData.xml
// and will also print the generic character class stats to a textbox.
private void loadPlayerCharacterButton_Click(object sender, RoutedEventArgs e)
{
if (File.Exists("NameData.xml"))
{
XmlSerializer sr = new XmlSerializer(typeof(NameSavingInformation));
FileStream read = new FileStream("NameData.xml", FileMode.Open, FileAccess.Read, FileShare.Read);
NameSavingInformation nameInfo = (NameSavingInformation)sr.Deserialize(read);
playerNameTextBox.Text = nameInfo.GeneratedName;
}
BaseClassStats bClass = new BaseClassStats();
bClass.health = 200;
bClass.power = 50;
bClass.specAttkPower = 200;
bClass.speed = 50;
string bClassStats = "Your current stats are :" + "\n \n" +
"Health : " + bClass.health + "\n \n" +
"Power : " + bClass.power + "\n \n" +
"Special Attack" + "\n" + "Power : " + bClass.specAttkPower + "\n \n" +
"Speed : " + bClass.speed;
playerClassTextBox.Text = bClassStats;
}
// This will print 10 characters randomly from the array to a texbox.
private void createPartyButton_Click(object sender, RoutedEventArgs e)
{
string[] partyCharacters =
{
"Barbarian",
"Elf",
"Wizard",
"Dragon",
"Knight",
"Cleric",
"Theif",
"Pyromancer",
"Brute",
"Unkindled"
};
Random r = new Random();
int rSelect = r.Next(0, 9);
int rs1 = rSelect;
int rs2 = rSelect;
int rs3 = rSelect;
int rs4 = rSelect;
int rs5 = rSelect;
int rs6 = rSelect;
int rs7 = rSelect;
int rs8 = rSelect;
int rs9 = rSelect;
int rs10 = rSelect;
// not sure how to set the listBox to = the result?
For this example let's suppose that your class is called Character and the constructor already exists as per points 2 and 3.
For point 4, you could instantiate a List<Character> and then use a loop, which iterates 10 times to fill it with 10 randomly generated characters, if you instantiate the List inside the loop it will be disposed of automatically upon each iteration finishing.
List<Character> characters = new List<Character>();
for(i = 0; i < 10; i++;)
{
Character character = new Character();
character.Generate(); //A method that would randomly generate a new character
characters.Add(character);
}
Point 5, Though you have not added anything to state the actual contents of the class, it is worth assuming that there is in the "stats" a type, health and money (just an example)
This point can be done by adding a label or text box (not enabled) to the form and writing the stats to it, considering that there are multiple stats, it might be worth considering using a listBox too.
Finally for point 6 you should be using different form controls to make an intuitive interface, such as + and - symbols for improving and worsening stats, images that relate to the individual stats and even a limit to total stat points (20 total divided between 3 stats for example) In this there should be a button that calls the print method in the character class. This means that the method must be public!

If-else statement with radio buttons and a for loop

I've gotten an issue that keeps happening and I'm unsure what the problem is. I need to create a program in Microsoft Visual studio where radioButton1 is for finding the sum of consecutive numbers and radioButton2 is for finding the factorial of a number.
There will be three buttons, one for FOR loop, one for WHILE loop, and one for DO-WHILE loop. I'm working on the FOR button.
What I'm trying to do is by making a selection, then pressing one of the buttons, it'll find the answer using the loop clicked in a Message box.
This is what I've gotten so far:
private void button1_Click(object sender, System.EventArgs e)
{
if ((radioButton1.Checked == true) && (radioButton2.Checked == false))
{
int sum = 0;
int number = int.Parse(numericUpDown1.Value.ToString());
for (int i = 1; i <= number; i++)
{
sum = sum + i;
MessageBox.Show("The sum of the consecutive numbers leading up to " + number + " is " + sum + ".");
}
MessageBox.Show("The sum of the consecutive numbers leading up to " + number + " is " + sum + ".");
}
else if ((radioButton2.Checked == true) && (radioButton1.Checked == false))
{
int product = 1;
int number = int.Parse(numericUpDown1.Value.ToString());
for (int i = 1; i <= number; i++)
{
product *= i;
MessageBox.Show("The factorial of the numbers leading up to " + number + " is " + product + ".");
}
MessageBox.Show("The factorial of the numbers leading up to " + number + " is " + product + ".");
}
else
{
MessageBox.Show("Invalid");
}
}
I keep receiving this message:
"'Lab5'does not contain a definition for 'radioButton2.CheckedChanged' and no extension method 'radioButton2.CheckChanged' accepting a first argument of type 'Lab5' could be found (are you missing a using directive or an assembly reference?)."
And I honestly have no idea what that means.
Any help would be greatly appreciated.
I want to keep it in an if-else statement simply because I don't want the message box for radioButton1 to pop up when radioButton2 is selected.
You have probably inadvertently added a handler to that radio button (e.g. by double clicking it in the designer) and then removed it. When the solution is building, it is looking for that function but can't find it.
Check Lab5.Designer.cs for the radioButton2 code. It will look something like this:
this.radioButton1.AutoSize = true;
this.radioButton1.Location = new System.Drawing.Point(102, 162);
this.radioButton1.Name = "radioButton1";
this.radioButton1.Size = new System.Drawing.Size(85, 17);
this.radioButton1.TabIndex = 1;
this.radioButton1.TabStop = true;
this.radioButton1.Text = "radioButton1";
this.radioButton1.UseVisualStyleBackColor = true;
this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButton1_CheckedChanged); /* THis is the offending line! */
That last line is trying to add an event handler referencing a non-existant method. You can either remove it here.
Also, when the program builds, you should be able to double-click on the compile error and the IDE will take you to the source of the problem.
Looks like a homework. Either way, you need to implement a handler for your radio buttons for the event CheckChanged. Also, if you put those radio buttons in a group, either one can be checked and in the checkchanged event you should populate some functionMode or something. Example, when RadioButton1 is checked, you should store a variable that'll contain which formula to apply, on the other one checked you should change that. And in the button submit event, use that variable to see the current mode and apply that formula.

displaying X number of items from a list

I have a List of Items that I want to print to the console for debugging but I only want to display 3 Items at one time but this is within a function so It needs to know where it left off so it can start from the next 3 items from the previous ones how could I accomplish this?
static void list(Boolean nextPage)
{
static List<Item> _items = new List<Item>();
//if(nextPage) display next page
Console.WriteLine("Press numbers 1 - 3 to display more info on an item or press 4 for next page...\r\n");
int count = 0;
foreach (Item item in _items)
{
Console.WriteLine((count + 1) + ": Name: " + item.itemName + ", ");
count++;
}
Console.WriteLine(("4: Next Page");
}
Make your function non-static, add a variable to store the last item that you have displayed so far, use that variable to decide where to start the next listing, and advance that value by three each time that you go through the function.
Here is a rough approximation to how you can do it - this will probably not work as a copy-paste replacement of your function, but it should give you an idea of what to do:
int lastPosition;
void list(Boolean nextPage) {
if(!nextPage) {
lastPosition = 0;
}
Console.WriteLine("Press numbers 1 - 3 to display more info on an item or press 4 for next page...\r\n");
foreach (Item item in _items.Skip(lastPosition).Take(3))
{
Console.WriteLine((count + 1) + ": Name: " + item.itemName + ", ");
}
lastPosition += 3;
Console.WriteLine(("4: Next Page");
}
Everything created within the scope of a method is trashed when you exit it, unless you return a value toward whoever called the method.
So, you have two choices (or more, but here's two):
private static Item lastItem;
With this, you store inside your class the last item displayed and retrieve it the next time.
or
public static Item itemlist(Boolean nextPage, Item nextItem)
{
// Some logic
return lastItem;
}
And let whoever call your method handle the variable.

Categories

Resources