Divide in C# with incorrect result [duplicate] - c#

I'm currently writing a program that requires a preview of a live display, but the preview, of course, is scaled down. However, when I scale the PictureBox down, the size is incorrect. For the scale to be correct the width and height need to be at a 4:3 ratio. Here's the code:
private void FindOptimalRes(PictureBox picBox)
{
double h = Height / 4;
double ratio = 4 / 3;
picBox.Size = new Size((int)(h * ratio), (int)h);
}
In testing, Height (the height of the form) is 400, so, the width of the new size should be 133. But it always gets resized to 100×100! Why?

4 and 3 are both ints, so it gets turned to 1. Make them something floating-point:
double ratio = 4.0 / 3.0;
Note that you're also making the same mistake with Height (it doesn't matter right now, but it will - change it to 4.0). And if this is the actual code, why divide by four to multiply by four again?
private void FindOptimalRes(PictureBox picBox)
{
picBox.Size = new Size(Height / 3, Height / 4);
}

You are doing integer division:
double ratio = 4 / 3; // evaluates to 1
This won't give you the value you are looking for because the decimal point is being truncated, thus evaluating to 1 instead of 1.333. At least one of the operands needs to be a double:
double ratio = 4.0 / 3.0; // evaluates to 1.333
Same goes for Height. Change the 4 to 4.0.

C#'s math is "correct". The understanding of what is being done is .. missing :-)
The expression 4 / 3 (of type int / int) will evaluate to the integer value 1 as it is using integer division (both operands are integers). The resulting 1 is then implicitly coerced to a double value on assignment.
On the other hand 4d / 3 will "work" (and results in a double 1.333_) because now it is double / int -> double / double (by promotion) -> double using the appropriate floating point division.
Similarly, for Height / 4 (assuming Height is an integer), these would work:
(double)Height / 4 // double / int -> double
Height / 4d // int / double -> double
(double)Height / (double)4 // double / double -> double
Happy coding!

Make sure division result is double
double ratio = (double) 4 / 3; // double division
and no need to set your input values to double.
var num1 = // an integer number
var num2 = // an integer number
//result is integer, because of integer/integer uses 'integer division'
double result = num1 / num2;
//result is double , because of you forced to 'double division'
double result = (double) num1 / num2;

Maybe you should do a decimal division and not integer division:
double h = Height / 4.0;
double ratio = 4 / 3.0;
If C# Math was off many things around the world would be off as well.

You are doing integer division.
what you need to do is this :
private void FindOptimalRes(PictureBox picBox)
{
double h = Height / 4D; // or Height / 4.0
double ratio = 4D / 3D; // or 4.0 / 3.0
picBox.Size = new Size((int)(h * ratio), (int)h); // Size is now correct [133,100]
}
when you do a mathematical operation with an integer literal (no decimal places) it is implicitly typed as an int.
Simply appending a capital D at the end of your literals (4D, 3D) will type them as doubles, and your math will be correct. Alternatively you can write 4.0, 3.0

Related

Matching excels rounding in a C# application

I am currently in the process of turning a rather lofty Excel sheet that is used for calculating scientific values into a C# application. However, I am hitting some problems in regards to the rounding.
All of my values are stored as doubles, and when you perform a small number of operations on them they match the excel sheet within acceptable accuracy (5 or 6 decimal places). When they are put through rather large operations with division, multiplication, square roots. They start to drift off by quite a large margin. I switched the entire code base to decimals at another point to test if it resolved this issue, it lessened the gap but the issue still remained.
I am aware this is due to the nature of decimal numbers in software development, but it's imperative I match excels rounding as much as possible. Research on this topic points me towards the standards that excel uses to round and it seems C# by default uses a slightly different one. Despite learning of this I am still unsure of how to proceed on replicating excels rounding. I'm wondering if anyone has any advice or previous experience on this topic?
Any help would be greatly appreciated.
EDIT : I would just like to clarify that I am not rounding my numbers whatsoever. The rounding on both the sheet and my code is implicitly being applied. I have tested the same formulas inside of a totally different software package (A form builder called K2). The resulting numbers match my c# application so it seems excels implicit rounding differs in some way.
One of the offending formulas:
(8.04 * Math.Pow(10, -5)) *
(Math.Pow(preTestTestingDetails.PitotCp, 2)) * (DeltaH) *
(tempDGMAverage + 273.0) /
(StackTemp + 273) *
((preTestTestingDetails.BarometricPressure / 0.133322 +
((preTestTestingDetails.StackStaticPressure / 9.80665) / 13.6)) /
(preTestTestingDetails.BarometricPressure / 0.133322)) *
(preTestTestingDetails.EstimatedMolWeight /
((preTestTestingDetails.EstimatedMolWeight * (1 - (EstimatedMoisture / 100))) +
(18 * (EstimatedMoisture / 100)))) *
Math.Pow((1 - (EstimatedMoisture / 100)), 2) *
(Math.Pow(preTestTestingDetails.NozzleMean, 4));
In C# the result of
int x = 5;
var result = x / 2; // result is 2 and of type int
... because an integer division is performed. So if integers are involved (not a double with no decimals, but a value of type int or long), make sure to convert to double before dividing.
int x = 5;
double result = x / 2; // result is 2.0 because conversion to double is made after division
This works:
int x = 5;
var result = (double)x / 2; // result is 2.5 and of type double
int x = 5;
var result = x / 2.0; // result is 2.5 and of type double
int x = 5;
var result = 0.5 * x; // result is 2.5 and of type double
The only place in your formula where this could happen is EstimatedMoisture / 100, in case EstimatedMoisture is of type int. If this is the case, fix it with EstimatedMoisture / 100.0.
Instead of 8.04 * Math.Pow(10, -5), you can write 8.04e-5. This avoids rounding effects of Math.Pow!
I don't know how Math.Pow(a, b) works, but the general formula is a^b=exp(b*ln(a)). So instead of writing Math.Pow(something, 2), write something * something. This is both, faster and more accurate.
Using constants for magic numbers adds clarity. Using temps for common sub-expressions makes the formula more readable.
const double mmHg_to_kPa = 0.133322;
const double g0 = 9.80665;
var p = preTestTestingDetails;
double moisture = EstimatedMoisture / 100.0;
double dryness = 1.0 - moisture;
double pressure_mmHg = p.BarometricPressure / mmHg_to_kPa;
double nozzleMean2 = p.NozzleMean * p.NozzleMean;
double nozzleMean4 = nozzleMean2 * nozzleMean2;
double result = 8.04E-05 *
p.PitotCp * p.PitotCp * DeltaH * (tempDGMAverage + 273.0) / (StackTemp + 273.0) *
((pressure_mmHg + p.StackStaticPressure / g0 / 13.6) / pressure_mmHg) *
(p.EstimatedMolWeight / (p.EstimatedMolWeight * dryness + 18.0 * moisture)) *
dryness * dryness * nozzleMean4;
Why not use 273.15 instead of 273.0 if precision is a concern?

Why am I getting zero when I multiply doubles?

I made this line of code while debugging:
double hola = (1 / 2) * (double)x.height;
height is a double. Hola is just a temporary name.
When I debug, I see that x.height = 1, and hola = 0.
What did I do wrong? I'm pretty sure I made some really simple mistake..
Also when I remove the double casting that I do to x.height I still get hola = 0.
1 / 2 is zero, remainder one. Zero times anything is zero.
Did you mean to write 1.0 / 2.0?
1 and 2 are both int, so the result of 1/2 will be cast (truncated) to an int. 0.5 -> 0.
You need to make sure either of the operands supports decimal points:
double hola = (1.0 / 2) * (double)x.height;
Or:
double hola = ((double)1 / 2) * (double)x.height;
Dividing two integers will performs an integer division, which gives the result also in the same type(fractional part is truncated).Where a non-integer division(here double) on int arguments by explicitly casting at least one of the arguments to a double. So your code will be :
double hola = (1 / (double)2) * (double)x.height;
OR
double hola = ((double)1 / 2) * (double)x.height;

Implicitly converting int to double

So, I'm a tad confused. I was under the impression that this should work:
In this case, both a and b are ints (Counters to be exact).
As the result of a / b may possibly contain decimal places, ints obviously won't work.
Therefore, I delared a new double and performed the calculation inside it like this:
double texturefactor = ((a / b) * 10);
This doesn't work as I expected, and the result of a / b is always that which I would get if I performed the calculation using an int to store the results.
On the other hand, this works:
double calculate1 = a;
double calculate2 = b;
double texturefactor = ((calculate1 / calculate2) * 10);
Couple of perhaps stupid questions-
1. I'm sure this ought to work- I know that in certain situations VS will complain that I've tried to implicitly convert from one type to another- That's what I'm trying to do! Why doesn't it, and have I missed something? :)
2. Should I just convert the counters a and b to doubles and save myself the trouble of the conversion, or is that trouble?
The result of a / b is another integer, so even if you do this, the damage has already been done:
double texturefactor = ((a / b) * 10);
Try casting one of your inner variables to a double:
var texturefactor = (( (double)a / b) * 10);
The result of (double)a / b will be a double, and you won't lose your fraction.
To answer your second question:
Should I just convert the counters a and b to doubles
That'd work too. If you change those to double, then you wouldn't have to perform the above cast.
The expression, including the types of subexpressions, is evaluated from inside to outside:
double texturefactor = ((a / b) * 10);
When the compiler analyses a / b, it has no idea that the result will later on be converted to double, so it just compiles the computation as an integer division.
Explicitly casting one of the two operands to double right there is enough to avoid that confusion:
double texturefactor = (((double)a / b) * 10);
When you have the expression (a / b), the C# compiler ignores that it will later be assigned to a double. It focuses only on that expression, and sees int / int, so it uses integer division. This means that your result is rounded down to the next integer before it's ever converted to a double.
You need to make sure C# treats the division as a division of doubles, not ints, for example:
double texturefactor = (((double)a / b) * 10); // or
double texturefactor = 10d * a / b; // or
double texturefactor = 10.0 * a / b;
The reason this double texturefactor = ((a / b) * 10); not working is that all the parameters on the right hand side are of type int thus the calculations are being done in int not double as you think.
You can explicitly cast a or b to double. Like
double texturefactor = (((double) a / b) * 10);
In your second code since you defined a and b as double, now the calculations are done in double type.
You need to cast the int values to double:
int a = some_value;
int b = some_value;
double texturefactor = (double)a / b * 10;
Integer division will not have decimal values just because you are assigning their values to a double variable.
If you want precision, then your second method is quite good.
double calculate1 = a;
double calculate2 = b;
double texturefactor = ((calculate1 / calculate2) * 10);
The above is good.
I will not advise you to cast it into double as there is some overhead to pay.
Result of dividing two integers is always a integer. So you need to
double texturefactor = (((double)a / b) * 10);
Therefore, I delared a new double and performed the calculation inside it like this:
Ah, no.
double texturefactor = ((a / b) * 10);
Basic syntax. YOu declare a double (texturefactor). You assign it the result of a pure integer opeation - (a/b)*10
Due to precedences this is a/b (integer, throw away digits) times 10. THEN implicit converison.
Typical beginner mistake - but one MANY do.
You want a double arithmetic, make sure any of the elements is a double, like for example:
((double) a/b)*10
will do a floating piont conversion for all elements.

C# - Data Type for value 0.5

I have a calculation for example 2/4 = 0.5, except I can't find a data type that will store this value! Every time I make the calculation it says 0.
Anyone have any suggestions?
Either double or decimal will work fine.
However, if you just write:
// Wrong
double x = 2 / 4;
then it will still use integer division - because both of the operands for the division operator are of type int.
You can either cast either or both of the operands to double, or use a double literal for either or both of them:
// Any of these...
double x = (double) 2 / 4;
double x = 2 / (double) 4;
double x = (double) 2 / (double) 4;
double x = 2.0 / 4;
double x = 2 / 4.0;
double x = 2.0 / 4.0;
double x = 2d / 4;
double x = 2 / 4d;
double x = 2d / 4d;
Note that both double and decimal are floating point types. They don't represent arbitrary rational numbers (fractions). For example, neither can accurately represent 1/3. If you need a rational number type, you'll have to write your own or look for a third party implementation.
Make sure at least one of the divisor or the dividend is a floating number:
double d = 2 / 4.0;
Console.WriteLine(d): // Writes: 0.5
Use 2/4.0 to force it to use floating point arithmetics. Then you can store it in a double:
double d = 2/4.0;
If in the real code you have variables, cast the divisor to a double:
int i = 2;
int j = 4;
double d = i/(double)j;
You can cast,
double value = (double)2/4;
or you can provide your input with decimals
double value = 2.0/4.0;
Either float or double will do the job.
float x = 2f / 4f;
double x = 2d / 4d;
Note that you can specify constant values to be float or doubles by appending the appropriate character (f or d).
The important thing to remember is that the first data type (on the left) will determine the data type of the result. EDIT: actually, in this case either value being a float/double will work
So...
var x = 2 / 4;//x is int (0)
var x = 2f / 4;//x is float (0.5f)
var x 2d / 4;//x is double (0.5d)
C# will automatically convert int to float/double so...
float x = 2 / 4;//result type is int, but gets stored as convert float
Anyway, hope that helps explain some things

Why is modulus operator not working for double in c#?

Consider this:
double x,y;
x =120.0;
y = 0.05;
double z= x % y;
I tried this and expected the result to be 0, but it came out 0.04933333.
However,
x =120.0;
y = 0.5;
double z= x % y;
did indeed gave the correct result of 0.
What is happening here?
I tried Math.IEEERemainder(double, double) but it's not returning 0 either. What is going on here?
Also, as an aside, what is the most appropriate way to find remainder in C#?
Because of its storage format, doubles cannot store every values exactly as is is entered or displayed. The human representation of numbers is usually in decimal format, while doubles are based on the dual system.
In a double, 120 is stored precisely because it's an integer value. But 0.05 is not. The double is approximated to the closest number to 0.05 it can represent. 0.5 is a power of 2 (1/2), so it can be stored precisely and you don't get a rounding error.
To have all numbers exactly the same way you enter / display it in the decimal system, use decimal instead.
decimal x, y;
x = 120.0M;
y = 0.05M;
decimal z = x % y; // z is 0
You could do something like:
double a, b, r;
a = 120;
b = .05;
r = a - Math.floor(a / b) * b;
This should help ;)
I believe if you tried the same with decimal it would work properly.
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems can help you understand why you get these "strange" results. There's a particular precision that floating point numbers can have. Just try these queries and have a look at the results:
0.5 in base 2
0.05 in base 2
Modulus should only be used with integer. The remainder come from an euclidean division. With double, you can have unexpected results.
See this article
This is what we use.. :)
public double ModuloOf(double v1, double v2)
{
var mult = 0;
//find number of decimals
while (v2 % 1 > 0)
{
mult++;
v2 = v2 * 10;
}
v1 = v1 * Math.Pow(10, mult);
var rem = v1 % v2;
return rem / Math.Pow(10, mult);
}

Categories

Resources