C# Mathemathics - c#

I wanted to ask a question about a calculation I had today in C#.
double expenses = (pricePen + priceMark + priceLitres) - discount / 100*(pricePen + priceMark + priceLitres); //Incorrect
double expenses = (pricePen + priceMark + priceLitres) - (pricePen + priceMark + priceLitres)* discount/100; //Correct
So as you can see at the end of the equation I had to multiply the brackets by the integer named "discount", which is obviously a discount percentage.
When I change the places of that value whether it would be in front of the brackets or behind the brackets the answer will always be different, but in Maths I even checked myself that I should get the same answer even if the value is placed in front of the brackets to multiply or placed behind the brackets to multiply again, but C# doesn't think so.
I wanted to ask people, how does C# actually calculate this and why am I getting different results at the end? (Result should be 28.5, not 38)
[Data: pricePen = 11.6; priceMark = 21.6; priceLitres = 4.8; discount = 25;]
(I know that the question is irrelevant.)

In first line after dividing by 100 the result is in an integer. For that the rest of division get lost. So the multiplication has a lower result.
In second line the multiplication has the correct result and the rest of devision is lower than one.

So I know its already answered but if you want to learn more about divisions with int
here it is:
for example:
float value = 3/4 you would expect it to be 0.75 but that's not the case.
Because when the Compiler goes through the values 3 and 4 he makes des Literal of the highest data type - in this case (int)-.
That means the result of this division will be "0".75 because int has no floating numbers and just cuts it off. Then the program just takes that value and puts it in the float value ...
so the result will be
"3/4" 0 ->"float value" 0.0 = 0.0
Some guys before me already told you the solution to that problem like making one divisor to float with .0
float value = 3.0/4
or you can tell the Compiler to store the value in a float Literal with the (float) "command"
float value = (float) 3/4
I hope it helped you explain why you did that :)

To avoid these problems makes sure you are doing math with floating point types, and not int types. In your case discount is an int and thus
x * (discount / 100) = x * <integer>
Best to define a function to do the calculation which forces the type
double DiscountedPrice(double price, double discount)
{
return price - (discount/100) * price;
}
and then call it as
var x = DiscountedPrice( pricePen + priceMark + priceLitres, 15);
In the above scenario, the compiler will force the integer 15 to be converted into an double as a widening conversion (double has more digits than integer).

Related

C#. Strange behavior of double

Here is the code which made me post this question.
// int integer;
// int fraction;
// double arg = 110.1;
this.integer = (int)(arg);
this.fraction = (int)((arg - this.integer) * 100);
The variable integer is getting 110. That's OK.
The variable fraction is getting 9, however I am expecting 10.
What is wrong?
Update
It seems I have discovered that the source of the problem is subtraction
arg - this.integer
Its result is 0.099999999999994316.
Now I am wondering how I should correctly subtract so that the result was 0.1.
You have this:
fraction = (int)((110.1 - 110) * 100);
The inner part ((110.1 - 110) * 100), will be 9.999999
When you cast it to int, it will be round off to 9
This is because of "floating point" (see here) limitations:
Computers always need some way of representing data, and ultimately
those representations will always boil down to binary (0s and 1s).
Integers are easy to represent, but non-integers are a bit more
tricky. Consider the following var:
double x = 0.1d;
The variable x will actually store the closest available double to
that value. When you understand this, it becomes obvious why some
calculations seem to be "wrong".
If you were asked to add a third to a third, but could only use 3
decimal places, you'd get the "wrong" answer: the closest you could
get to a third is 0.333, and adding two of those together gives 0.666,
rather than 0.667 (which is closer to the exact value of two thirds).
Update:
In financial applications or where the numbers are so important to be exact, you can use decimal data type:
(int)((110.1m - 110) * 100) //will be 10 (m is decimal symbol)
or:
decimal arg = 110.1m;
int integer = (int)(arg); //110
decimal fraction = (int)((arg - integer) * 100); //will be 10
It is because you are using double, precision gets rounded, if you want it to be 10 use decimal type:
check the following:
int integer;
int fraction;
decimal arg = 110.1M;
integer = (int)(arg);
decimal diff = arg - integer;
decimal multiply = diff * 100;
fraction = (int)multiply;//output will be 10 as you expect

How to extract N number of decimal point without round off?

I want to extract N number of decimal points after the value without doing round up.
Below is the example :
string val = null;
int numberOfDigitsAfterDecimalPoint = 2;
double val1 = 56423747.61;
double val2 = 56423996.57;
val = ((56423747.61 / 56423996.57) * 100).ToString(); //99.9995587692912
val = String.Format("{0:n" + numberOfDigitsAfterDecimalPoint.ToString() + "}", (100 * Convert.ToDecimal(val)) / 100); //100.00
But problem here is it is rounding up and I am getting 100.00 which I don't want because I want exact value with decimal point i.e 99.99 without any kind of round up.
I searched and came to conclusion(my thinking) that best way to handle this is by extracting number of digits after decimal point with substring method but still I am not sure that whether i am thinking in wrong or right way.
Expected output with numberOfDigitsAfterDecimalPoint = 2 :
99.99
Update
I am not having a fixed value to get after decimal point because it is dependent on numberOfDigitsAfterDecimalPoint variable. Apart from that can have very large value based on which I am calculating val; that is why I was thinking to use substring function in which I won't have any problem related to round off, as oppose to mathematical calculation or math function.
How can I do this in efficient way without compromising any value?

how to leave decimal places to 1 without rounding

I need to convert my value 2.8634 to 2.8. I tried the following ,
var no = Math.Round(2.8634,2,MidpointRounding.AwayFromZero)
I'm getting 2.87.
Suggest me some ideas how to convert.
Thanks
This might do the trick for you
decimal dsd = 2.8634m;
var no = Math.Truncate(dsd * 10) / 10;
Math.Truncate calculates the integral part of a specified decimal number. The number is rounded to the nearest integer towards zero.
You can also have a look on the difference between Math.Floor, Math.Ceiling, Math.Truncate, Math.Round with an amazing explanation.
Use this one.Hope this will work for you.
var no = Math.Round(2.8634,1,MidpointRounding.AwayFromZero)
It's a tad more cryptic (but more efficient) than calling a Math method, but you can simply multiply the value by 10, cast to an integer (which effectively truncates the decimal portion), and then divide by 10.0 (or 10d/10f, all just to ensure we don't get integer division) to get back the value you are after. I.e.:
float val = 2.8634;
val = ((int)(val * 10)) / 10.0;

How to divide an int to receive a decimal? [duplicate]

This question already has answers here:
How can I divide two integers to get a double?
(9 answers)
Closed 7 years ago.
I'm trying to calculate the area of a sector but when I divide angleParse by 360 and times it by radiusParse, I will sometimes receive a output of 0.
What happens and where do I need to fix it? (Sorry, if this is a weird question but I started learning C# yesterday, also I just started using StackOverflow today)
Frostbyte
static void AoaSc()
{
Console.WriteLine("Enter the radius of the circle in centimetres.");
string radius = Console.ReadLine();
int radiusParse;
Int32.TryParse(radius, out radiusParse);
Console.WriteLine("Enter the angle of the sector.");
string sectorAngle = Console.ReadLine();
int angleParse;
Int32.TryParse(sectorAngle, out angleParse);
double area = radiusParse * angleParse / 360;
Console.WriteLine("The area of the sector is: " + area + "cm²");
Console.ReadLine();
}
You've encountered integer division. If a and b are int, then a / b is also an int, where the non-integer part has been truncated (i.e. everything following the decimal point has been cut off).
If you want the "true" result, one or more of the operands in your division needs to be a floating point. Either of the following will work:
radiusParse * (double)angleParse / 360;
radiusParse * angleParse / 360.0;
Note that it's not sufficient to cast radiusParse to double, because the / operator has higher precedence than * (so the integer division happens first).
Finally, also note that decimal in .NET is its own type, and is distinct from float and double.
I think if you divide it by 360.0 it will work.
Alternatively declare a variable of type decimal and set this to 360.
private decimal degreesInCirle = 360;
// Other code removed...
double area = radiusParse * angleParse / degreesInCirle;

Comparing double values in C#

I've a double variable called x.
In the code, x gets assigned a value of 0.1 and I check it in an 'if' statement comparing x and 0.1
if (x==0.1)
{
----
}
Unfortunately it does not enter the if statement
Should I use Double or double?
What's the reason behind this? Can you suggest a solution for this?
It's a standard problem due to how the computer stores floating point values. Search here for "floating point problem" and you'll find tons of information.
In short – a float/double can't store 0.1 precisely. It will always be a little off.
You can try using the decimal type which stores numbers in decimal notation. Thus 0.1 will be representable precisely.
You wanted to know the reason:
Float/double are stored as binary fractions, not decimal fractions. To illustrate:
12.34 in decimal notation (what we use) means
1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2
The computer stores floating point numbers in the same way, except it uses base 2: 10.01 means
1 * 21 + 0 * 20 + 0 * 2-1 + 1 * 2-2
Now, you probably know that there are some numbers that cannot be represented fully with our decimal notation. For example, 1/3 in decimal notation is 0.3333333…. The same thing happens in binary notation, except that the numbers that cannot be represented precisely are different. Among them is the number 1/10. In binary notation that is 0.000110011001100….
Since the binary notation cannot store it precisely, it is stored in a rounded-off way. Hence your problem.
double and Double are the same (double is an alias for Double) and can be used interchangeably.
The problem with comparing a double with another value is that doubles are approximate values, not exact values. So when you set x to 0.1 it may in reality be stored as 0.100000001 or something like that.
Instead of checking for equality, you should check that the difference is less than a defined minimum difference (tolerance). Something like:
if (Math.Abs(x - 0.1) < 0.0000001)
{
...
}
You need a combination of Math.Abs on X-Y and a value to compare with.
You can use following Extension method approach
public static class DoubleExtensions
{
const double _3 = 0.001;
const double _4 = 0.0001;
const double _5 = 0.00001;
const double _6 = 0.000001;
const double _7 = 0.0000001;
public static bool Equals3DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _3;
}
public static bool Equals4DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _4;
}
...
Since you rarely call methods on double except ToString I believe its pretty safe extension.
Then you can compare x and y like
if(x.Equals4DigitPrecision(y))
Comparing floating point number can't always be done precisely because of rounding. To compare
(x == .1)
the computer really compares
(x - .1) vs 0
Result of sybtraction can not always be represeted precisely because of how floating point number are represented on the machine. Therefore you get some nonzero value and the condition evaluates to false.
To overcome this compare
Math.Abs(x- .1) vs some very small threshold ( like 1E-9)
From the documentation:
Precision in Comparisons
The Equals method should be used with caution, because two apparently equivalent values can be unequal due to the differing precision of the two values. The following example reports that the Double value .3333 and the Double returned by dividing 1 by 3 are unequal.
...
Rather than comparing for equality, one recommended technique involves defining an acceptable margin of difference between two values (such as .01% of one of the values). If the absolute value of the difference between the two values is less than or equal to that margin, the difference is likely to be due to differences in precision and, therefore, the values are likely to be equal. The following example uses this technique to compare .33333 and 1/3, the two Double values that the previous code example found to be unequal.
So if you really need a double, you should use the techique described on the documentation.
If you can, change it to a decimal. It' will be slower, but you won't have this type of problem.
Use decimal. It doesn't have this "problem".
Exact comparison of floating point values is know to not always work due to the rounding and internal representation issue.
Try imprecise comparison:
if (x >= 0.099 && x <= 0.101)
{
}
The other alternative is to use the decimal data type.
double (lowercase) is just an alias for System.Double, so they are identical.
For the reason, see Binary floating point and .NET.
In short: a double is not an exact type and a minute difference between "x" and "0.1" will throw it off.
Double (called float in some languages) is fraut with problems due to rounding issues, it's good only if you need approximate values.
The Decimal data type does what you want.
For reference decimal and Decimal are the same in .NET C#, as are the double and Double types, they both refer to the same type (decimal and double are very different though, as you've seen).
Beware that the Decimal data type has some costs associated with it, so use it with caution if you're looking at loops etc.
Official MS help, especially interested "Precision in Comparisons" part in context of the question.
https://learn.microsoft.com/en-us/dotnet/api/system.double.equals
// Initialize two doubles with apparently identical values
double double1 = .333333;
double double2 = (double) 1/3;
// Define the tolerance for variation in their values
double difference = Math.Abs(double1 * .00001);
// Compare the values
// The output to the console indicates that the two values are equal
if (Math.Abs(double1 - double2) <= difference)
Console.WriteLine("double1 and double2 are equal.");
else
Console.WriteLine("double1 and double2 are unequal.");
1) Should i use Double or double???
Double and double is the same thing. double is just a C# keyword working as alias for the class System.Double
The most common thing is to use the aliases! The same for string (System.String), int(System.Int32)
Also see Built-In Types Table (C# Reference)
Taking a tip from the Java code base, try using .CompareTo and test for the zero comparison. This assumes the .CompareTo function takes in to account floating point equality in an accurate manner. For instance,
System.Math.PI.CompareTo(System.Math.PI) == 0
This predicate should return true.
// number of digits to be compared
public int n = 12
// n+1 because b/a tends to 1 with n leading digits
public double MyEpsilon { get; } = Math.Pow(10, -(n+1));
public bool IsEqual(double a, double b)
{
// Avoiding division by zero
if (Math.Abs(a)<= double.Epsilon || Math.Abs(b) <= double.Epsilon)
return Math.Abs(a - b) <= double.Epsilon;
// Comparison
return Math.Abs(1.0 - a / b) <= MyEpsilon;
}
Explanation
The main comparison function done using division a/b which should go toward 1. But why division? it simply puts one number as reference defines the second one. For example
a = 0.00000012345
b = 0.00000012346
a/b = 0.999919002
b/a = 1.000081004
(a/b)-1 = 8.099789405475458e-5‬
1-(b/a) = 8.100445524503848e-5‬
or
a=12345*10^8
b=12346*10^8
a/b = 0.999919002
b/a = 1.000081004
(a/b)-1 = 8.099789405475458e-5‬
1-(b/a) = 8.100445524503848e-5‬
by division we get rid of trailing or leading zeros (or relatively small numbers) that pollute our judgement of number precision. In the example, the comparison is of order 10^-5, and we have 4 number accuracy, because of that in the beginning code I wrote comparison with 10^(n+1) where n is number accuracy.
Adding onto Valentin Kuzub's answer above:
we could use a single method that supports providing nth precision number:
public static bool EqualsNthDigitPrecision(this double value, double compareTo, int precisionPoint) =>
Math.Abs(value - compareTo) < Math.Pow(10, -Math.Abs(precisionPoint));
Note: This method is built for simplicity without added bulk and not with performance in mind.
As a general rule:
Double representation is good enough in most cases but can miserably fail in some situations. Use decimal values if you need complete precision (as in financial applications).
Most problems with doubles doesn't come from direct comparison, it use to be a result of the accumulation of several math operations which exponentially disturb the value due to rounding and fractional errors (especially with multiplications and divisions).
Check your logic, if the code is:
x = 0.1
if (x == 0.1)
it should not fail, it's to simple to fail, if X value is calculated by more complex means or operations it's quite possible the ToString method used by the debugger is using an smart rounding, maybe you can do the same (if that's too risky go back to using decimal):
if (x.ToString() == "0.1")
Floating point number representations are notoriously inaccurate because of the way floats are stored internally. E.g. x may actually be 0.0999999999 or 0.100000001 and your condition will fail. If you want to determine if floats are equal you need to specify whether they're equal to within a certain tolerance.
I.e.:
if(Math.Abs(x - 0.1) < tol) {
// Do something
}
My extensions method for double comparison:
public static bool IsEqual(this double value1, double value2, int precision = 2)
{
var dif = Math.Abs(Math.Round(value1, precision) - Math.Round(value2, precision));
while (precision > 0)
{
dif *= 10;
precision--;
}
return dif < 1;
}
To compare floating point, double or float types, use the specific method of CSharp:
if (double1.CompareTo(double2) > 0)
{
// double1 is greater than double2
}
if (double1.CompareTo(double2) < 0)
{
// double1 is less than double2
}
if (double1.CompareTo(double2) == 0)
{
// double1 equals double2
}
https://learn.microsoft.com/en-us/dotnet/api/system.double.compareto?view=netcore-3.1

Categories

Resources