cannot implicitly convert 'void' to 'decimal' - c#

Getting this error at futureValue = this.CalculateFutureValue(futureValue, monthlyInvestment, monthlyInterestRate, months);and I'm having trouble figuring out how to fix it. When I look up the error online most of the answers say to make the method decimal instead of void so it can have a return type.
But in part of the requirements for the code "rework the CalculateFutureValue method by making it a void function and adding a fourth parameter representing the future value amount to be returned by this method."
private void btnCalculate_Click(object sender, EventArgs e)
{
decimal monthlyInvestment = Convert.ToDecimal(txtMonthlyInvestment.Text);
decimal yearlyInterestRate = Convert.ToDecimal(txtInterestRate.Text);
int years = Convert.ToInt32(txtYears.Text);
int months = years * 12;
decimal monthlyInterestRate = yearlyInterestRate / 12 / 100;
decimal futureValue = 0m;
futureValue = this.CalculateFutureValue(futureValue, monthlyInvestment, monthlyInterestRate, months);
txtFutureValue.Text = futureValue.ToString("c");
txtMonthlyInvestment.Focus();
}
/
private void CalculateFutureValue(decimal futureValue, decimal monthlyInvestment, decimal monthlyInterestRate, int months)
{
for (int i = 0; i < months; i++)
{
futureValue = (futureValue + monthlyInvestment) * (1 + monthlyInterestRate);
}
}

Here is what they mean by the requirement: instead of this
decimal ComputeSomething(decimal x, decimal y) {
return x*x + y*y;
}
...
decimal result = ComputeSomething(10.234M, 20.5M);
do this:
void ComputeSomething(decimal x, decimal y, out res) {
res = x*x + y*y;
}
...
decimal result;
ComputeSomething(10.234M, 20.5M, out result);
Note the out qualifier in front of the additional parameter res. This means that the parameter is "output", i.e. your method must assign it some value before completion.
The assignment to res inside ComputeSomething will become an assignment to variable result.

You need to pass the variable by reference:
private void CalculateFutureValue(ref decimal futureValue, decimal monthlyInvestment, decimal monthlyInterestRate, int months){ ... }
and
this.CalculateFutureValue(ref futureValue, monthlyInvestment, monthlyInterestRate, months);
See this documentation.
If futureValue had not been initialized with a value before passing it to CalculateFutureValue, the out keyword would have needed to be used in place of ref.

Related

Set the number of decimal places in data type decimal

I have got a model which contains a property of data type decimal. I want to make sure the getter method returns a deterministic value in every case.
The data type model stores the number of non-significant decimal places, but does not seem to expose a method or property to control it.
The following program illustrates the findings:
class Program
{
static void Main(string[] args)
{
decimal d1 = decimal.Parse("1200.00");
Console.WriteLine(d1); // Prints 1200.00
decimal d2 = decimal.Parse("1200");
Console.WriteLine(d2); // Prints 1200
decimal d3 = correctDecimalPlaces(d2);
Console.WriteLine(d3); // Prints 1200.00
}
static decimal correctDecimalPlaces(decimal d)
{
return decimal.Parse(d.ToString("0.00"));
}
}
How can I control the number of decimal places used in decimal data type?
To change the number of decimal values, I convert the decimal to a string and back to a decimal. Do you know a cleaner way to do it?
Adding 0.00m to a decimal number, although counterintuitive, will force it to have at least 2 decimal points. If you need to ensure it has exactly 2, you can apply decimal.Round() also.
static decimal correctDecimalPlaces(decimal d)
{
return decimal.Round(d + 0.00m, 2);
}
I found this way (if return string is good for you):
public static class Extensions
{
public static string ToStringDecimal(this decimal d, byte decimals)
{
var fmt = (decimals>0) ? "0." + new string('0', decimals) : "0";
return d.ToString(fmt);
}
public static string ToStringDecimal(this decimal? d, byte decimals)
{
if (!d.HasValue) return "";
return ToStringDecimal(d.Value, decimals);
}
}
Or we use like this:
public static decimal? RoundTo2Decimal(decimal? pValue)
if (pValue.HasValue)
{
if (pValue.Value >= 0)
{
decimal vAluePos = pValue.Value * 100 + 0.5m;
return Math.Floor(vAluePos) / 100;
}
decimal vAlueNeg = Math.Abs(pValue.Value) * 100 + 0.5m;
return -(Math.Floor(vAlueNeg) / 100);
}
return null;
}

How to multiply two numbers and get the SUM every two numbers is multiply?

Good day everyone! Hope this work. I have to 2 textboxes and I convert it to integer the num1 and num2. I want to display it into textSubtotal. For example 10 * 10 = 100. I want to multiply another 2 numbers the value is 20 * 20 = 400. Add it to 100 so the answer will be 100 + 400 = 500. But the problem is I received an error in this line textSubtotal.Text = Convert.ToString(float.Parse(textSubtotal.Text) + sum) Input string was not in a correct format. Can somebody help me regarding to my problem?
private void buttonOrder_Click(object sender, EventArgs e)
{
float num1, num2, product = 0, sum = 0;
num1 = float.Parse(textPrice.Text);
num2 = float.Parse(textQuantity.Text);
product = num1 * num2; sum = sum + product;
textSubtotal.Text = Convert.ToString(float.Parse(textSubtotal.Text) + sum);
}
You don't need to struggle with Textbox string conversions to do that. Use a private field:
private float subTotal = 0; // this would be a field in your class
private void buttonOrder_Click(object sender, EventArgs e)
{
float num1 = float.Parse(textPrice.Text);
float num2 = float.Parse(textQuantity.Text);
subTotal += num1 * num2;
textSubtotal.Text = subTotal;
}
You should check that the two fields contain actual numeric values (see float.TryParse()). Also, consider using decimal (not float) for this kind of calculations.

Using Decimals in C#

private void textBox1_TextChanged(object sender, EventArgs e)
{
int x = 0;
if (Int32.TryParse(textBox1.Text, out x))
{
var y = 1000000;
var answer = x * y;
displayLabel2.Text = answer.ToString();
}
else
{
displayLabel2.Text = "error";
}
}
All of this code works. But I don't know how to use it if a decimal is inputed. Currently it reads numerical values fine and calculates them fine. But I need it to allow decimal points to be inputted.
Ex. if someone inputed 4.7, then I need 4.7 to be multiplied by 1000000.
You need to use a number type that has precision. You can use either floating types (double or float) or the decimal type.
private void textBox1_TextChanged(object sender, EventArgs e)
{
decimal x = 0;
if (decimal.TryParse(textBox1.Text, out x))
{
var y = 1000000.0M;
var answer = x * y;
displayLabel2.Text = answer.ToString();
}
else
{
displayLabel2.Text = "error";
}
}
You could use decimal instead of int:
decimal x = 0;
if (decimal.TryParse(textBox1.Text, out x))

How to pass value from one method to another?

I am working on a employee paycheck calculator using several private methods. The methods will determine overtime hours and regular hours. I also must create methods for regular pay and overtime pay. My question is can I feed the results from the hours methods into the methods that will determine pay? If that is possible, how would it work? The method in question is CalculateBasePayAmount--can I pass a result from another method into here?
Here is a look at what I've got so far. Thanks for any help anyone could provide!
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
//Determine Hours Method
private decimal DetermineBasePayHours(decimal parhoursWorked)
{
decimal baseHours = 0;
decimal overtimeHours = 0;
if (parhoursWorked <= 40)
{
baseHours = parhoursWorked;
}
else if (parhoursWorked > 40)
{
overtimeHours = parhoursWorked - 40;
baseHours = parhoursWorked - overtimeHours ;
}
return baseHours;
}
private decimal DetermineOverTimeHours(decimal parHoursWorked, string parCategory)
{
decimal overtimeHours = 0;
if (parHoursWorked > 40 && parCategory!="MGR")
{
overtimeHours = parHoursWorked - 40;
}
return overtimeHours;
}
private decimal CalculateBasePayAmount(decimal basePayHours, string parCategory)
{
decimal basePay = 0;
decimal mgrWage = 20;
decimal salesWage = 15;
decimal staffWage = 10;
basePayHours= DetermineBasePayHours(basePayHours);
if(parCategory == "MGR" && basePayHours > 40)
{
basePay = 40 * mgrWage;
}
else
{
basePay = basePayHours * mgrWage;
}
if (parCategory =="SR")
{
basePay = basePayHours * salesWage;
}
else if (parCategory == "STF")
{
basePay = basePayHours * staffWage;
}
return basePay;
}
protected void butCalcPay_Click(object sender, EventArgs e)
{
////1. Declare Variables
//decimal mgrWage = 20;
//decimal salesWage = 15;
//decimal staffWage = 10;
//decimal basePay = 0M;
//decimal salesOvertime = 22.50M;
//decimal staffOvertime = 15;
//decimal overtimeHours = 0;
//decimal overtimePay = 0;
//decimal totalPay = 0;
decimal totalHours = 0;
decimal bpHours;
decimal otHours;
string empCat;
decimal basePay;
//2. Get Values for Variables
totalHours = Convert.ToDecimal(txtNumberHours.Text);
empCat = Convert.ToString(ddlCategory.SelectedValue);
// 3. Methods Called
bpHours = DetermineBasePayHours(totalHours);
otHours = DetermineOverTimeHours(totalHours, empCat);
basePay = CalculateBasePayAmount(totalHours, empCat);
// 4. Display Results
lblbasePay.Text = "Base Pay " + basePay.ToString("C");e here
can I feed the results from the hours methods into the methods that will determine pay?
In a manner of speaking, yes. Though I think the confusion is coming from the way you describe it and the terminology you use.
It's not entirely clear to me what specific values you're looking for in this case, but it looks like your methods essentially just accept some values, run some calculations, and return some values. Any code which call those functions will then get those returned values and can use them to call other functions. As a contrived example:
private int Method1(int someValue)
{
// perform some calculation, then...
return anotherValue;
}
private int Method2(int someValue)
{
// perform some calculation, then...
return anotherValue;
}
Then consuming code would be able to use those functions to perform larger calculations:
var calculatedValue = Method1(5);
var furtherCalculatedValue = Method2(calculatedValue);
This essentially "feeds the results" of the first function into the second function, in the sense that the result of the first function is then used as an input for the second function. The functions don't have any knowledge of each other, they don't "feed data to each other", in this case they simply return values based on calculations. Consuming code can choose to use the result of one function as a parameter to another function.
You do need to read more on programming and how/why we have methods that return values that the ones you mentioned above. Using your code above you'll want to use their values like this:
// basePayHours is the decimal amount returned by DetermineBasePayHours.
var basePayHours = DetermineBasePayHours(parhoursWorked);
// overTimeHours is the decimal amount returned by DetermineOverTimeHours.
var overTimeHours = DetermineOverTimeHours(parHoursWorked, parCategory);
// basePayAmount is the decimal amount returned by CalculateBasePayAmount.
var basePayAmount = CalculateBasePayAmount(basePayHours, parCategory);
delegate can also be used when a method is needed from another one .

Doubles, Ints, Math.Round in C#

I have to convert a double value x into two integers as specified by the following...
"x field consists of two signed 32 bit integers: x_i which represents the integral part and x_f which represents the fractional part multiplied by 10^8. e.g.: x of 80.99 will have x_i as 80 and x_f as 99,000,000"
First I tried the following, but it seems to fail sometimes, giving an xF value of 1999999 when it ought to be 2000000
// Doesn't work, sometimes we get 1999999 in the xF
int xI = (int)x;
int xF = (int)(((x - (double)xI) * 100000000));
The following seems to work in all the cases that I've tested. But I was wondering if there's a better way to do it without the round call. And also, could there be cases where this could still fail?
// Works, we get 2000000 but there's the round call
int xI = (int)x;
double temp = Math.Round(x - (double)xI, 6);
int xF = (int)(temp * 100000000);
The problem is (1) that binary floating point trades precision for range and (2) certain values, such as 3.1 cannot be repsented exactly in standard binary floating point formats, such as IEEE 754-2008.
First read David Goldberg's "What Every Computer Scientist Should Know About Floating-Point Arithmetic", published in ACM Computing Surveys, Vol 23, No 1, March 1991.
Then see these pages for more on the dangers, pitfalls and traps of using floats to store exact values:
http://steve.hollasch.net/cgindex/coding/ieeefloat.html
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Why roll your own when System.Decimal gives you precise decimal floating point?
But, if your going to do it, something like this should do you just fine:
struct WonkyNumber
{
private const double SCALE_FACTOR = 1.0E+8 ;
private int _intValue ;
private int _fractionalValue ;
private double _doubleValue ;
public int IntegralValue
{
get
{
return _intValue ;
}
set
{
_intValue = value ;
_doubleValue = ComputeDouble() ;
}
}
public int FractionalValue
{
get
{
return _fractionalValue ;
}
set
{
_fractionalValue = value ;
_doubleValue = ComputeDouble() ;
}
}
public double DoubleValue
{
get
{
return _doubleValue ;
}
set
{
this.DoubleValue = value ;
ParseDouble( out _intValue , out _fractionalValue ) ;
}
}
public WonkyNumber( double value ) : this()
{
_doubleValue = value ;
ParseDouble( out _intValue , out _fractionalValue ) ;
}
public WonkyNumber( int x , int y ) : this()
{
_intValue = x ;
_fractionalValue = y ;
_doubleValue = ComputeDouble() ;
return ;
}
private void ParseDouble( out int x , out int y )
{
double remainder = _doubleValue % 1.0 ;
double quotient = _doubleValue - remainder ;
x = (int) quotient ;
y = (int) Math.Round( remainder * SCALE_FACTOR ) ;
return ;
}
private double ComputeDouble()
{
double value = (double) this.IntegralValue
+ ( ( (double) this.FractionalValue ) / SCALE_FACTOR )
;
return value ;
}
public static implicit operator WonkyNumber( double value )
{
WonkyNumber instance = new WonkyNumber( value ) ;
return instance ;
}
public static implicit operator double( WonkyNumber value )
{
double instance = value.DoubleValue ;
return instance ;
}
}
I think using decimals solve the problem, because internally they really use a decimal representation of the numbers. With double you get rounding errors when converting the binary representation of a number to decimal. Try this:
double x = 1234567.2;
decimal d = (decimal)x;
int xI = (int)d;
int xF = (int)(((d - xI) * 100000000));
EDIT: The endless discussion with RuneFS shows that the matter is not that easy. Therefore I made a very simple test with one million iterations:
public static void TestDecimals()
{
int doubleFailures = 0;
int decimalFailures = 0;
for (int i = 0; i < 1000000; i++) {
double x = 1234567.7 + (13*i);
int frac = FracUsingDouble(x);
if (frac != 70000000) {
doubleFailures++;
}
frac = FracUsingDecimal(x);
if (frac != 70000000) {
decimalFailures++;
}
}
Console.WriteLine("Failures with double: {0}", doubleFailures); // => 516042
Console.WriteLine("Failures with decimal: {0}", decimalFailures); // => 0
Console.ReadKey();
}
private static int FracUsingDouble(double x)
{
int xI = (int)x;
int xF = (int)(((x - xI) * 100000000));
return xF;
}
private static int FracUsingDecimal(double x)
{
decimal d = (decimal)x;
int xI = (int)d;
int xF = (int)(((d - xI) * 100000000));
return xF;
}
In this Test 51.6% of the doubles-only conversion fail, where as no conversion fails when the number is converted to decimal first.
There are two issues:
Your input value will rarely be equal to its decimal representation with 8 digits after the decimal point. So some kind of rounding is inevitable. In other words: your number i.20000000 will actually be slightly less or slightly more than i.2.
Casting to int always rounds towards zero. This is why, if i.20000000 is less than i.2, you will get 19999999 for the fractional part. Using Convert.ToInt32 rounds to nearest, which is what you'll want here. It will give you 20000000 in all cases.
So, provided all your numbers are in the range 0-99999999.99999999, the following will always get you the nearest solution:
int xI = (int)x;
int xF = Convert.ToInt32((x - (double)xI) * 100000000);
Of course, as others have suggested, converting to decimal and using that for your calculations is an excellent option.

Categories