C# use of unassigned local variable on three variables - c#

I am trying to create a code that allows me to calculate the price of two products however there are some changes throughout the code, (I want to aplly discounts according to the volume that will be bought. However when I make counts with three variables it show use of unassigned local variable...
static void Main(string[] args)
{
double peso_morango, peso_maca, total;
double totalmorango, totalmaca, final_real;
const double percentual = 0.1;
Console.WriteLine("Insira a quantidade de morangos, em kg: ");
peso_morango = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Insira a quantidade de maça, em kg:");
peso_maca = Convert.ToInt32(Console.ReadLine());
if (peso_morango <= 5)
{
totalmorango = 2.50 * peso_morango;
}
else if (peso_morango > 5)
{
totalmorango = 2.20 * peso_morango;
}
else if (peso_morango > 8)
{
totalmorango = 1.62 * peso_morango;
}
else if (peso_maca <= 5)
{
totalmaca = 1.62 * peso_maca;
}
else if (peso_maca > 5)
{
totalmaca = 2.20 * peso_maca;
}
else if (peso_maca > 8)
{
totalmaca = 1.35 * peso_maca;
}
else if (peso_maca + peso_morango > 8)
{
total = totalmorango + totalmaca;
final_real = (total) - (percentual * total);
Console.WriteLine(" O valor final é de {0} euros", final_real);
}
else if (totalmaca + totalmorango > 25)
{
total = totalmorango + totalmaca;
final_real = (total) - (percentual * total);
Console.WriteLine(" O valor final é de {0} euros", final_real);
}
else if (peso_maca + peso_morango < 8)
{
Console.WriteLine(" O valor final é de {0} euros", final_real);
}
else if (totalmorango + totalmaca < 25)
{
Console.WriteLine(" O valor final é de {0} euros", final_real);
}
Console.ReadKey();
}

I understand this is not a solution to your problem, but the only part of the code which will run is:
static void Main(string[] args)
{
double peso_morango, peso_maca, total;
double totalmorango, totalmaca, final_real;
const double percentual = 0.1;
Console.WriteLine("Insira a quantidade de morangos, em kg: ");
peso_morango = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Insira a quantidade de maça, em kg:");
peso_maca = Convert.ToInt32(Console.ReadLine());
if (peso_morango <= 5)
{
totalmorango = 2.50 * peso_morango;
}
else if (peso_morango > 5)
{
totalmorango = 2.20 * peso_morango;
}
Console.ReadKey();
}
This is because EITHER peso_morango <= 5 OR peso_morango > 5 will be true.
I don't think "else if" does what you expect it to do.

To make such mistake means that you're a beginner in programming and you'll probably do with some explanation to what is happening.
We gonna use int for this example.
When you declare variable like this int x; that is basically say hey i need some memory allocate some for me, How much of memory depend on the int
Now if you ever done some C++ or any unmanaged programming languages (Means the compiler doesn't do half of the work for you), you would understand that
int x; in memory will actually be holding some values from previous operations we don't know about, So you'll have to explicitly clean it from that garbage.
In C# that is basically the same, however here we have the compiler complaining to help you out, since you want some memory it needs to be fresh so you'll have to zero it out int x = 0;
So you'll have to zero it out or assign it a value you want to start with, you can use negative values too if you want to keep the zero, depending on the Valuetype int or uint etc....

totalmorango and totalmaca are not initialized, they are just declared. You need to initialize your variables with proper Initial values first before you use it.
By looking into your code, you are using them in addition operation.
assuming if any if elseif are not satisfy (where you assign value to them), you need them to be 0. (also it is unit value for addition operation)
replace your line
double totalmorango, totalmaca, final_real;
with
double totalmorango = 0, totalmaca = 0, final_real = 0;
Update
however whatever error you are facing will be solved by above steps, but as mentioned by others too. your checking ,
else if (peso_morango > 5)
is not appropriate if you want to check if value of peso_morango is greater than 5 but also if you want that to be less or equal to 8.
you should be checking else if (peso_morango > 5 && peso_morango <= 8)
And also you should be having separate condition checking for peso_maca . like,
if (peso_maca <= 5)
{
totalmaca = 1.62 * peso_maca;
}
else if (peso_maca > 5 && peso_maca <= 8)
{
totalmaca = 2.20 * peso_maca;
}
else// no need to check else part "peso_maca > 8" as it always be true
{
totalmaca = 1.35 * peso_maca;
}
and same way, separate condition checking for later part too.
By doing this, you will not even need to do,
double totalmorango = 0, totalmaca = 0, final_real = 0;
as suggested in first part of answer.

Related

What will be the output of this and how?

The output of this code is
0 1 2 3
But I am not getting the factorial part. I mean 1!=1 (i.e. i factorial equals to 1), so it does not satisfy the condition, so type for input 2 and 3, but they get printed as output?
static void Main(string[] args)
{
int i = 0;
int b = 8, a = 32;
for (i = 0; i <= 10; i++)
{
if ((a / b * 2)== 2)
{
Console.WriteLine( i + " ");
continue;
}
else if (i!=4)
Console.Write(i + " ");
else
break;
}
Console.ReadLine();
}
OK, let's see:
int b = 8, a = 32;
...
a / b * 2 == 32 / 8 * 2 == 4 * 2 == 8
That's why if ((a / b * 2) == 2) will never succeed, and so we can drop this if and simplify the loop into
for (i = 0; i <= 10; i++)
if (i != 4) // i != means "i doesn't equal", not "i factorial equals"
Console.Write(i + " "); // print 0, 1, 2, 3
else
break; // break on 4
Here we can clearly see that the routine will be printing out i up to 4 So you have
0 1 2 3
Side note: in order to avoid such errors, format out your code and let the compiler help you:
i!=4 // Bad, it can be read in different ways (not equal or factorial)
i != 4 // i is not equal to 4
i! = 4 // assign 4 to i factorial: compile time error
i! == 4 // i factorial equals to 4: compile time error - C# doesn't have factorials

C# How would I convert grade percentages to letter grades?

Noob here. I have written a program that allows a user to enter how many grades they would like to input into an array, and then lets them enter the grades for the number of indexes they chose. I am trying to output the total percentage grade based on the inputted grades, and also output the actual letter grade, but I am having trouble figuring out what I would code to convert to letter grades. Any help is appreciated.
Code:
public static void Main(string[] args)
{
int ARRAYLENGTH = 0;
int i = 0;
double sum = 0;
Console.WriteLine("How many scores would you like to enter? ");
ARRAYLENGTH = Convert.ToInt32(Console.ReadLine());
string[] test = new string[ARRAYLENGTH];
for (i = 0; i < test.Length; i++)
{
Console.Write("Enter your test score " + (i + 1) + ": ");
test[i] =
Console.ReadLine();
}
for (i = 0; i < test.Length; i++)
{
sum = sum +
Convert.ToDouble(test[i].Trim());
}
Console.WriteLine("\nThis is your average = " + (sum / test.Length));
Console.WriteLine("\nYour grade is: ");//Not sure how this would work
Console.Write("\nPress the [Enter] key to exit.");
Console.ReadLine();
}
For one, you're better of doing some more assignment (rather than calculating the grade in the print statement) so I've included that below. Once you have the percentage in a var you just use an if/else or a switch to derive the letter grade.
double gradePer = sum / test.Length
string gradeLetter = "F";
if (gradePer >= 60 && gradePer < 70) {
gradeLetter = "D";
} else if (gradePer >= 70 && gradePer < 80) {
gradeLetter = "C";
} // you fill in the rest
Console.WriteLine("\nThis is your average = " + gradePer);
Console.WriteLine("\nYour grade is: " + gradeLetter);
I would use a switch, specificing a range of values for each letter
You can make a function to get your letter grade from the average you computed:
static char GetLetterGrade(double score)
{
if (score >= 90.0)
{
return 'A';
}
if (score >= 80.0)
{
return 'B';
}
if (score >= 70.0)
{
return 'C';
}
if (score >= 60.0)
{
return 'D';
}
return 'F';
}
In the simplest possible way... I would create a dictionary:
Key - Value
10 - A
9 - A
8 - B
7 - C
6 - D
5 - F
4 - F
3 - F
2 - F
1 - F
0 - F
Now that you have this dictionary set up, you can take the grade into your method, divide by 10, take the floor and find the entry associated with that value.
public class Grades
{
Dictionary<int, char> GradeValues { get; set; }
public Grades()
{
GradeValues.Add(10, 'A');
GradeValues.Add(9, 'A');
GradeValues.Add(8, 'B');
...
GradeValues.Add(0, 'F');
}
public char GetGrade(int grade)
{
char value = GradeValues[int.Floor(grade/10)];
if (value == null)
return 'F';
return value;
}
}
That being said, there are probably better ways to handle this.
Edit: This assumes that you don't have B- or other grades that happen when a grade of 88 is passed into the method.
If statements or cases would work great too, but I prefer this method of development. It is easier to extend when you want to change a grade. You don't have to update the method. You only need to update the dictionary in the constructor.
Edit 2: I have seen that someone downvoted every answer. I upvoted the other answers as they are all valid...
You could just fill out the entire dictionary from 0 to 100 with the grade for that score.

error CS1525 why does it happen?

I don't know why but when I'm trying to compile the next code I'm getting error CS1525 and every ) at the end of every while command is being marked as an error:
static void PrintArray(string[] arr)
{
int i, sum = 0, subb = 0, pow, x;
char opper;
Console.WriteLine("how many numbers does your calculation have?");
i = Convert.ToInt16(Console.ReadLine());
arr = new string[i];
for (i = 0; i < arr.Length; i++)
{
Console.WriteLine("enter num {0}" + i);
arr[i] = Console.ReadLine();
Console.WriteLine("arr[{0}] = {1}" + i, arr[i]);
}
Console.WriteLine("what do you want to do?");
opper = Convert.ToChar(Console.ReadLine());
while (opper = +)
{
for (i = 0; i < arr.Length; i++)
{
sum = sum + Convert.ToInt16(arr[i]);
}
Console.WriteLine("your sum is " + sum);
}
while (opper = -)
{
for (i = 0; i < arr.Length; i++)
{
subb = subb + Convert.ToInt16(arr[i]);
}
Console.WriteLine("your subb is" + subb);
}
while (opper = *)
{
pow = Convert.ToInt16(arr[0]);
for (i = 1; i < arr.Length; i++)
{
pow = pow * Convert.ToInt16(arr[i]);
}
Console.WriteLine("the resolt is " + pow);
}
while (opper = &)
{
x = Convert.ToInt16(arr[i]);
for (i = 0; i < arr.Length; i++)
{
x = x / Convert.ToInt16(arr[i]);
}
Console.WriteLine("your resolt is " + x);
}
Console.ReadKey();
}
I will be glad if someone can finally explain that to me...
Given the lines (for example)
opper = Convert.ToChar(Console.ReadLine());
while (opper = +)
It looks like you're trying to compare the character input to an operator. You'll want to change the assignment operator to a comparison operator, and compare the character to another character, like so:
opper = Convert.ToChar(Console.ReadLine());
while (opper == '+')
user1673882 is correct here about the cause of the compile error. However, there are several other significant bugs you should be aware of as well.
As for the original compile issue, you have two issues with the following line (and all similar lines);
while (opper = +)
First, = (single "equals" sign) is assignment, not comparison. You want to use == here instead.
Secondly, + is not a character in this case, it's an operation. (In fact, the compiler can't infer exactly which operator it might be).
Even if you get this to compile, though, it won't work because all of your loops are infinite loops. Consider this example:
char myChar = 'a';
// Infinite loop
while (myChar == 'a')
{
Console.WriteLine("Test");
}
How could this possibly get out of the loop, given that myChar will always be a?
A few other miscellaneous bugs follow:
subb = subb + Convert.ToInt16(arr[i]);
This could be shortened with
subb += Convert.ToInt16(arr[i]);
or possibly even
subb += (short)arr[i];
Also, I'm assuming this shouldn't be "+" since that's exactly the same operation you're doing if the operation is "+" (i.e. the outcome of "+" and "-" should be exactly the same).
x = x / Convert.ToInt16(arr[i]);
First, same cleanup as above:
x /= (short)arr[i];
Secondly, you never test for division by 0 here, so this might throw an exception.
Third, I'm not sure what type x is, but "short" is definitely not closed over division - i.e.:
short a = ...
short b...
// May not be another short
Console.WriteLine(a / b);
Actually, this applies to multiplication, subtraction, and addition to some extent too in this case since shorts have a finite size. Consider the following code:
short overflow = short.MaxValue;
// -32768
overflow++;
// +32767
overflow--;
// -32768 again
overflow++;
// -32767
overflow++;
checked
{
overflow = short.MaxValue;
// Now this results in an OverflowException
overflow++;
}
One more example:
short testArithmetic = 1;
// This gives us the result that 1 / 2 = 0.
testArithmetic /= 2;
// Set this back to 1 for the next operation
testArithmetic = 1;
// This is 0.0 too!
double testArithmeticFloat = testArithmetic / 2;
// This gives us the result we'd expect
testArithmeticFloat = 1.0 / 2.0;
// This'll compile just fine, but you get a DivideByZeroException when you try to execute it
testArithmetic /= 0;

Why this sin(x) function in C# return NaN instead of a number

I have this function wrote in C# to calc the sin(x). But when I try with x = 3.14, the printed result of sin X is NaN (not a number),
but when debugging, its is very near to 0.001592653
The value is not too big, neither too small. So how could the NaN appear here?
static double pow(double x, int mu)
{
if (mu == 0)
return 1;
if (mu == 1)
return x;
return x * pow(x, mu - 1);
}
static double fact(int n)
{
if (n == 1 || n == 0)
return 1;
return n * fact(n - 1);
}
static double sin(double x)
{
var s = x;
for (int i = 1; i < 1000; i++)
{
s += pow(-1, i) * pow(x, 2 * i + 1) / fact(2 * i + 1);
}
return s;
}
public static void Main(String[] param)
{
try
{
while (true)
{
Console.WriteLine("Enter x value: ");
double x = double.Parse(Console.ReadLine());
var sinX = sin(x);
Console.WriteLine("Sin of {0} is {1}: " , x , sinX);
Console.ReadLine();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
It fails because both pow(x, 2 * i + 1) and fact(2 * i + 1) eventually return Infinity.
In my case, it's when x = 4, i = 256.
Note that pow(x, 2 * i + 1) = 4 ^ (2 * 257) = 2.8763090157797054523668883052624395737887631663 × 10^309 - a stupidly large number which is just over the max value of a double, which is approximately 1.79769313486232 x 10 ^ 308.
You might be interested in just using Math.Sin(x)
Also note that fact(2 * i + 1) = 513! =an even more ridiculously large number which is more than 10^1000 times larger than the estimated number of atoms in the observable universe.
When x == 3.14 and i == 314 then you get Infinity:
?pow(-1, 314)
1.0
?pow(x, 2 * 314 + 1)
Infinity
? fact(2 * 314 + 1)
Infinity
The problem here is an understanding of floating point representation of 'real' numbers.
Double numbers while allowing a large range of values only has a precision of 15 to 17 decimal digits.
In this example we are calculating a value between -1 and 1.
We calculate the value of the sin function by using the series expansion of it which is basically a the sum of terms. In that expansion the terms become smaller and smaller as we go along.
When the terms have reached a value less than 1e-17 adding them to what is already there will not make any difference. This is so because we only have 52 bit of precision which are used up by the time we get to a term of less than 1e-17.
So instead of doing a constant 1000 loops you should do something like this:
static double sin(double x)
{
var s = x;
for (int i = 1; i < 1000; i++)
{
var term = pow(x, 2 * i + 1) / fact(2 * i + 1);
if (term < 1e-17)
break;
s += pow(-1, i) * term;
}
return s;
}

How do I round doubles in human-friendly manner in C#?

In my C# program I have a double obtained from some computation and its value is something like 0,13999 or 0,0079996 but this value has to be presented to a human so it's better displayed as 0,14 or 0,008 respectively.
So I need to round the value, but have no idea to which precision - I just need to "throw away those noise digits".
How could I do that in my code?
To clarify - I need to round the double values to a precision that is unknown at compile time - this needs to be determined at runtime. What would be a good heuristic to achieve this?
You seem to want to output a value which is not very different to the input value, so try increasing numbers of digits until a given error is achieved:
static double Round(double input, double errorDesired)
{
if (input == 0.0)
return 0.0;
for (int decimals = 0; decimals < 17; ++decimals)
{
var output = Math.Round(input, decimals);
var errorAchieved = Math.Abs((output - input) / input);
if (errorAchieved <= errorDesired)
return output;
}
return input;
}
}
static void Main(string[] args)
{
foreach (var input in new[] { 0.13999, 0.0079996, 0.12345 })
{
Console.WriteLine("{0} -> {1} (.1%)", input, Round(input, 0.001));
Console.WriteLine("{0} -> {1} (1%)", input, Round(input, 0.01));
Console.WriteLine("{0} -> {1} (10%)", input, Round(input, 0.1));
}
}
private double PrettyRound(double inp)
{
string d = inp.ToString();
d = d.Remove(0,d.IndexOf(',') + 1);
int decRound = 1;
bool onStartZeroes = true;
for (int c = 1; c < d.Length; c++ )
{
if (!onStartZeroes && d[c] == d[c - 1])
break;
else
decRound++;
if (d[c] != '0')
onStartZeroes = false;
}
inp = Math.Round(inp, decRound);
return inp;
}
Test:
double d1 = 0.13999; //no zeroes
double d2 = 0.0079996; //zeroes
double d3 = 0.00700956; //zeroes within decimal
Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 + "<br/><br/>");
d1 = PrettyRound(d1);
d2 = PrettyRound(d2);
d3 = PrettyRound(d3);
Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 +"<br/><br/>");
Prints:
0,13999
0,0079996
0,00700956
0,14
0,008
0,007
Rounds your numbers as you wrote in your example..
I can think of a solution though it isn't very efficient...
My assumption is that you can tell when a number is in the "best" human readable format when extra digits make no difference to how it is rounded.
eg in the example of 0,13999 rounding it to various numbers of decimal places gives:
0
0.1
0.14
0.14
0.14
0.13999
I'd suggest that you could loop through and detect that stable patch and cut off there.
This method seems to do this:
public double CustomRound(double d)
{
double currentRound = 0;
int stability = 0;
int roundLevel = 0;
while (stability < 3)
{
roundLevel++;
double current = Math.Round(d, roundLevel);
if (current == currentRound)
{
stability++;
}
else
{
stability = 1;
currentRound=current;
}
}
return Math.Round(d, roundLevel);
}
This code might be cleanable but it does the job and is a sufficient proof of concept. :)
I should emphasise that that initial assumption (that no change when rounding) is the criteria we are looking at which means that something like 0.3333333333 will not get rounded at all. With the examples given I'm unable to say if this is correct or not but I assume if this is a double issues that the problem is with the very slight variations from the "right" value and the value as a double.
Heres what I tried:
public decimal myRounding(decimal number)
{
double log10 = Math.Log10((double) number);
int precision = (int)(log10 >= 0 ? 0 : Math.Abs(log10)) + (number < 0.01m ? 1 : 2);
return Math.Round(number, precision);
}
test:
Console.WriteLine(myRounding(0.0000019999m)); //0.000002
Console.WriteLine(myRounding(0.0003019999m)); //0.0003
Console.WriteLine(myRounding(2.56777777m)); //2.57
Console.WriteLine(myRounding(0.13999m)); //0.14
Console.WriteLine(myRounding(0.0079996m)); //0.008
You can do it without converting to string. This is what I created fast:
private static double RoundDecimal(double number)
{
double temp2 = number;
int temp, counter = 0;
do
{
temp2 = 10 * temp2;
temp = (int)temp2;
counter++;
} while (temp < 1);
return Math.Round(number, counter < 2 ? 2 : counter);
}
or
private static double RoundDecimal(double number)
{
int counter = 0;
if (number > 0) {
counter = Math.Abs((int) Math.Log10(number)) + 1;
return Math.Round(arv, counter < 2 ? 2 : counter);
}
After giving it another thought I did the following and looks like it does what I want so far.
I iterate over the number of digits and compare Round( value, number ) and Round( value, number + 1 ). Once they are equal (not == of course - I compare the difference against a small number) then number is the number of digits I'm looking for.
Double.ToString() can take a string format as an argument. This will display as many characters as you require, rounding to the decimal place. E.G:
double Value = 1054.32179;
MessageBox.Show(Value.ToString("0.000"));
Will display "1054.322".
Source
Generic formats (i.e, pre-generated)
How to generate custom formats
You can use no of digits with Math.Round Function
Double doubleValue = 4.052102;
Math.Round(doubleValue, 2);
This will return 4.05 as your required answer.
This is tested code, can u explain me how i am wrong. So i need to change.

Categories