decimal issue when adding a flat fee - c#

I have a small issue I believe the code is doing exactly what its suppose to be doing I have a function whereby I pass in an amount and I add a flat fee of 40 cents to it for the surcharge.
Below is how my current code is constructed
Double surcharge;
surcharge = 0.4 * moneyIn / 100;
If I pass 999.00m in as moneyIn it returns 0.3996 when in fact it should return 0.4 I'm unsure what I need to do to make it be 0.4.

You're not using decimal - you're using double. Use decimal everywhere (so moneyIn should be a decimal too). If you're actually using 999.00m for moneyIn, that would make it a decimal and your current code wouldn't even compile (as there are no implicit conversions between decimal and double).
Now your code doesn't actually talk about a flat fee of 40 cents - it's taking 0.4% of the original value. You should have something like:
decimal surcharge = 0.40m; // 40 cents
decimal total = moneyIn + surcharge;

Related

How to print all the decimal points without rounding up?

I want to calculate wind_chill by getting temp and wind_speed from user.
All variables are declared as double.
wind_chill = 35.74 + 0.6215 * temp + (0.4275 * temp - 35.75) * System.Math.Pow(wind_speed, 0.16);
I am getting this O/P:-
Enter temperature and wind Speed: 20 7 wind_chill is:11.03490062551
But I want to print all the decimal number till last without round up.
Expected O/P:-
wind_chill = 11.034900625509998
By declaring variables as decimal and converting all the values in decimal:
I am getting this output:
wind_chill = 11.034900625510096
Still not matching with the expected one. I searched But I didn't get my answer.How to get expected output?
Calculate the value with doubles. It is just that .NET will format the value to 15 characters when printing. Use R format to get all digits.
var wind_chill = WindChillDbl(20.0, 7.0);
Console.WriteLine(String.Format("{0:R}", wind_chill));
public static double WindChillDbl(double temp, double wind_speed)
{
return 35.74 + 0.6215 * temp + (0.4275 * temp - 35.75) * System.Math.Pow(wind_speed, 0.16);
}
"By default, the return value only contains 15 digits of precision although a maximum of 17 digits is maintained internally. If the value of this instance has greater than 15 digits, ToString returns PositiveInfinitySymbol or NegativeInfinitySymbol instead of the expected number. If you require more precision, specify format with the "G17" format specification, which always returns 17 digits of precision, or "R", which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision." MSDN
You can inspect your calculation to see that the values returned for most of the expression are accurate. The problem is with the accuracy of System.Math.Pow(wind_speed, 0.16);. If you look at wolframalpha for that input, there are signifcantly more digits provided than the 1.36526100641507 returned by Math.Pow.
The reason for this is because Math.pow uses float point types which are inaccurate by design. You may also be able to use BigInteger and figure out a way to make your equation work with that.
You can resolve this in a couple of ways:
Use BigRational
Rework the equation to somehow use BigInteger
See this question: What is the equivalent of the Java BigDecimal class in C#?, specifically this answer: https://stackoverflow.com/a/13813535/2127492
If you do go with the BigDecimal class provided in that answer, you will be able to make use of the method BigDecimal Pow(double basis, double exponent) to improve the accuracy your calculation.
You can see your calculation with the above class here.

double or decimal when calculating percent

Based on this thread decimal vs double!, decimal is always used for money. What is the proper way to define percent? like TaxPercent? If it's double then for calculating amount * 8% (double) you would have to cast it.
What's the proper way to define percent value (ie tax) and what would the calculation be.
Use the 'm' suffix to specify a literal as a decimal. So it must be 0.08m to ensure a double doesn't creep into the calculation.
decimal tax = amount * 0.08m;
You'll find a list of valid suffix characters in this post.

Issue with calculating financial values using float in C#

I was reading an article related to difference between Float and double. and they given an example as below :
Say you have a $100 item, and you give a 10% discount. Your prices are all in full dollars, so you use int variables to store prices. Here is what you get:
int fullPrice = 100;
float discount = 0.1F;
Int32 finalPrice = (int)(fullPrice * (1-discount));
Console.WriteLine("The discounted price is ${0}.", finalPrice);
Guess what: the final price is $89, not the expected $90. Your customers will be happy, but you won't. You've given them an extra 1% discount.
In above example, to calculate the final price they have used fullPrice * (1-discount) . why they used (1-disocunt) ? it should be fullPrice * discount.
so my confusion is about logic to calculate the final price. why thay used (1-discount) instead of discount ?
the final price is $89, not the expected $90
That's because when 0.1 is float, it is not exactly 0.1, it's a little more. When you subtract it from 1 to do the math, you get $89.9999998509884. Casting to int truncates the result to 89 (demo).
You can make this work by using decimal data type for your discount. This type can represent 0.1 without a precision loss (demo).
why they used (1-disocunt)
1 represents 100%. The price after discount is (100%-10%)=90%
This question is actually about math.
Let's suggest you have an item which costs 100$.
The seller provides a discount to you - 10%.
Now you need to calculate what is the final price of an item.
I.e., how much money should you give to get it?
The answer: you need to pay the full price of an item minus discounted price.
100% of a cost - 10% discount = 90% final price
That's why it is fullPrice * (1 - discount).
If you calculate it using your formula fullPrice * discount then it will mean that the item which costs 100$ will be sold for 10$ due to 10% discount - which is incorrect. Actually, this formula fullPrice * discount may be used for calculation of discounted amount.
There is nothing wrong with the overall logic of the above example, but it does have very unfortunate choice of data types. This leads to the values being converted implicitly to double, introducing a slight rounding error in the process. By casting back to int, the result is truncated. This greatly amplifies the rounding error.
This is a good example of a problem that frequently occurs when dealing with financial values in programming:
Float values do not tanslate well to decimal fractions.
Most new developers tend to think of float values as decimal fractions, because they are mostly represented by these, when converting them to strings and vice versa. This is not the case. Float values have their fractional part stored as binary fraction, as descibed here.
This makes float values (and their calulations) being slightly askew from their decimal representations. This is why the following results to $89,9999998509884:
double fullPrice = 100;
double discount = 0.1F;
double finalPrice = (fullPrice * (1 - discount));
Console.WriteLine("The discounted price is ${0}.", finalPrice);
(Not so) fun fact: The above will work fine when using float as data type, because the afforementioned error lies below the resolution of single precision values in this example and the assembly code does use double precision behind the scenes. When the result gets converted to single precision, the error gets lost.
One way out of this problem, is to use the data type decimal, that was construced to do calculations that have to translate directly to decimal fractions (as financial calculations do):
decimal fullPrice = 100;
decimal discount = 0.1m;
decimal finalPrice = (fullPrice * (1 - discount));
Console.WriteLine("The discounted price is ${0}.", finalPrice);
Another would be to round all results of floating point calculations, before displaying or storing them. For financial calculations one shoud use:
Math.Round([your value here], 2, MidpointRounding.AwayFromZero);

Issue with float datatype

I have a radnumeric textbox with monthly salary as below.
txtMonthlySalary.Text=816177200
Now I need to calculate the annual salary and save it as a float variable in the sql server table.My table is already an existing one and the annual salary field is type float.
Actual calculation on Annual salary gives following result:
Annual salary = 816177200 * 12 = 9,794,126,400
But in the program,
float Fld_AnnualSalary = float.Parse(txtMonthlySalary.Text) * 12;
gives result as 9,794,127,000
Here float data type rounds the result it seems,which is a big variation from the actual expected result.
How can I handle this issue,so that I can get the exact result on multiplication without rounding and save it in a float variable in sql sever table.
float and even double are not generally acceptable data types to work with real money values (as you just proved for yourself).
Please use Decimal in the code and corresponding type in SQL.
A float has a precision limited to about seven digits, and you are trying to do calculations on a nine-digit number 816177200.
The anwer by Alexeis Levenkov contains the solution to your problem. The Decimal data type can hold at least 28 significant digits.

Limiting double to 3 decimal places

This i what I am trying to achieve:
If a double has more than 3 decimal places, I want to truncate any decimal places beyond the third. (do not round.)
Eg.: 12.878999 -> 12.878
If a double has less than 3 decimals, leave unchanged
Eg.: 125 -> 125
89.24 -> 89.24
I came across this command:
double example = 12.34567;
double output = Math.Round(example, 3);
But I do not want to round. According to the command posted above,
12.34567 -> 12.346
I want to truncate the value so that it becomes: 12.345
Doubles don't have decimal places - they're not based on decimal digits to start with. You could get "the closest double to the current value when truncated to three decimal digits", but it still wouldn't be exactly the same. You'd be better off using decimal.
Having said that, if it's only the way that rounding happens that's a problem, you can use Math.Truncate(value * 1000) / 1000; which may do what you want. (You don't want rounding at all, by the sounds of it.) It's still potentially "dodgy" though, as the result still won't really just have three decimal places. If you did the same thing with a decimal value, however, it would work:
decimal m = 12.878999m;
m = Math.Truncate(m * 1000m) / 1000m;
Console.WriteLine(m); // 12.878
EDIT: As LBushkin pointed out, you should be clear between truncating for display purposes (which can usually be done in a format specifier) and truncating for further calculations (in which case the above should work).
I can't think of a reason to explicitly lose precision outside of display purposes. In that case, simply use string formatting.
double example = 12.34567;
Console.Out.WriteLine(example.ToString("#.000"));
double example = 3.1416789645;
double output = Convert.ToDouble(example.ToString("N3"));
Multiply by 1000 then use Truncate then divide by 1000.
If your purpose in truncating the digits is for display reasons, then you just just use an appropriate formatting when you convert the double to a string.
Methods like String.Format() and Console.WriteLine() (and others) allow you to limit the number of digits of precision a value is formatted with.
Attempting to "truncate" floating point numbers is ill advised - floating point numbers don't have a precise decimal representation in many cases. Applying an approach like scaling the number up, truncating it, and then scaling it down could easily change the value to something quite different from what you'd expected for the "truncated" value.
If you need precise decimal representations of a number you should be using decimal rather than double or float.
You can use:
double example = 12.34567;
double output = ( (double) ( (int) (example * 1000.0) ) ) / 1000.0 ;
Good answers above- if you're looking for something reusable here is the code. Note that you might want to check the decimal places value, and this may overflow.
public static decimal TruncateToDecimalPlace(this decimal numberToTruncate, int decimalPlaces)
{
decimal power = (decimal)(Math.Pow(10.0, (double)decimalPlaces));
return Math.Truncate((power * numberToTruncate)) / power;
}
In C lang:
double truncKeepDecimalPlaces(double value, int numDecimals)
{
int x = pow(10, numDecimals);
return (double)trunc(value * x) / x;
}

Categories