Difference between the values of a variable - c#

I wrote a code for checking typecasting in C#. The following code:
using System;
class Convert{
public static void Main(){
double a=14.25,b=26.12;
var z=(int)(a*b);
Console.WriteLine("z= "+z);
Console.ReadKey(true);
}
}
Gave output:
z=372
But when i modified the code a bit then i got a big difference between the value of z earlier and after modification.
using System;
class Convert{
public static void Main(){
double a=14.25,b=26.12;
var z=(int)a*b; // Modified part
Console.WriteLine("z= "+z);
Console.ReadKey(true);
}
}
Gave output:
z=365.68
I don't understand that why is there so much difference after removing the brackets from the original code?

Without the outer parentheses, the (int) cast applies to a only.
Therefore, you end up multiplying a truncated integer by a normal double, and type inference turns var into double.
With the parentheses, the cast applies to the result of the multiplication. Therefore, the entire result gets truncated, and type inference turns var into int.
Thus, changing var to double would have no effect on either example. (in the second case, it would assign the truncated int to a double variable)
Changing var to int would turn the second example into a compiler error.

brackets set prioryty
var z=(int)(a*b);//(a*b) cast to int
var z=(int)a*b;//a cast to int and myltiply with b

the priority of conversation operation () is bigger than multiply priority.
in first case you have:
double tmp = a*b;
int z = (int)tmp;
and in second:
int tmp = (int)a;
double z = tmp * b;

in the line
var z=(int)a*b;
a is being converted into an int before it is being multiplied. So it is going to be 14*26.12. Where in the 2nd case, you are multiplying a*b and converting the result into an int afterward.

Related

How to conversion of a boxed double type to int value type?

I am reading a book to pass the Microsoft Exam 70-483 and I got a little stuck on the following question :
The following code is boxed into object o.
double d = 11.5;
object o = d;
You’re asked to cast object o into int. What option should you use in your code?
int i = (int)o; //Option : A
int i = (int)(double)o; //Option : B
int i = (int)(float)(double)o; //Option : C
int i = (float)o; //Option : D
According to book, true answer is C, but I could not understand why the option b is wrong. When I try to run both of them, results are the same. Is there any difference option B and option C? What are your opinions?
In your given example, option B is totally fine.
Option A: You can't box and unbox different types. This will result in an InvalidCastException.
Option B: Totally fine. o will be unboxed in a double. Afterwards it will be cast (explicit) in an integer.
Option C: Like B, but before casting it into an integer, it will be casted to an float. The Result will stay the same. There is absolutly no need for the cast from double to float. It will always truncate.
But there are edges cases! (See below)
Option D: Can't use implicit cast from float to int. Same as A: InvalidCastException
So why C?
There are cases where rounding a double to an int differs from rounding a float to an int.
See the following answer from supercat
You can reproduce this by the following example:
static void Main(string[] args)
{
double val = 12344321.4999999991;
int a = (int)(float)val;
int b = (int)val;
Console.WriteLine(a);
Console.WriteLine(b);
Console.ReadLine();
}
The output will be:
12344322
12344321
So as you can see, casting to float first, will result in a different outcome.
Keep in mind, that these are edge cases and most likely academic problems.

Unboxing a boxed float to an int

I'm preparing for an exam and stumbled over a question regarding boxing/unboxing.
I always thought if i box let's say a float like this:
float x = 4.5f;
object o = x;
If a want a value type variable back from o, I will have to unbox it to a float.
float y = (float)o;
This should throw an exception:
int z = int(o);
If I want to cast the value stored in o to an int I will have to unbox it first and cast afterwards like this:
int z = (int)(float)o;
Now the question i stumbled upon:
Suppose you have a method like this:
public static void FloorTemperature(float degrees) {
object degreesRef = degrees;
`xxx`
Console.WriteLine(result);
}
You need to ensure the application does not throw exceptions on invalid conversions. Which code segment should you insert for xxx (I think invalid conversion are invalid cast exceptions):
(a) int result = (int)degreesRef;
(b) int result = (int)(float)degreesRef;
The correct solution is (a), but to me (b) looks correct. So can you please enlighten me? What am I missing?
Kind regards
You aren't missing anything
The answer should be (b) because:
(a) throws an exception since you are trying to cast object to int.
(b) is correct since you first cast it to float then you cast it to int which rounds it but doesn't throw an exception.

Why am I receiving a "call is ambigious" error when trying to user Math.Floor with an integer?

I've just made a small program that uses the Floor method:
public static void Main(string[] args)
{
int i;
decimal[] t = new decimal[30];
for(i=0; i<t.Length; i++)
{
t[i]=Math.Floor(i/6);
}
for(i=0; i<t.Length; i++)
{
Console.WriteLine(""+t[i]);
}
Console.ReadKey(true);
}
But it doesn't work. SharpDevelop returns this error:
The call is ambiguous between the following methods or properties: 'System.Math.Floor(decimal)' and 'System.Math.Floor(double)' (CS0121)
which is related to this line:
t[i] = Math.Floor(i/6);
Could someone explain me what's wrong?
Also: at first I tried writing int[] t = new int[30]; since my program only returns integers. But it returned a second error, saying that I should use the type decimal instead of the type int. I also tried to use the type float and the type double but it didn't work either. It seems only the type decimal works. I would also like to know why?
Could someone explain me what's wrong?
The compiler is telling you exactly what's wrong - the call is ambiguous. The fact that you're trying to use the result of the call to assign into a decimal array is irrelevant to the compiler - it only looks at the arguments to the method to try to work out what method you want to call.
The type of the expression i/6 is int, and that is convertible to both double and decimal, with neither conversion being "better" than the other, so the call is ambiguous. In fact, you don't really need the call at all - you're performing integer arithmetic anyway with the expression i / 6, which truncates towards zero - which is the equivalent to Floor for non-negative numbers. And you're only wanting to store integers anyway... All you need is:
public static void Main(string[] args)
{
// While "values" isn't a particularly descriptive name, it's better
// than "t"
int[] values = new int[30];
// Limit the scope of i - declare it in the loop header
for (int i = 0; i < values.Length; i++)
{
values[i] = i / 6;
}
// You don't need the index here, so use a foreach loop. Generally prefer
// foreach over for
foreach (int value in values)
{
// You don't need any string concatenation here...
Console.WriteLine(value);
}
Console.ReadKey(true);
}
The counter in your for loop is an integer.
An integer divided by an integer results in an integer.
Integers do not have a decimal portion, so calling Math.Floor is useless in the first place.
Because of this, there is no overload Floor(int).
An integer can be implicitly converted to double and decimal, both which have this overload.
Both are applicable and thus you get the following error.

casting ExecuteScalar() result c#

why would this work
int collectionCharge = (int)cmdCheck.ExecuteScalar();
but this produces an exception
double collectionCharge = (double)cmdCheck.ExecuteScalar();
System.InvalidCastException: Specified cast is not valid.
why would it not be valid?
EDIT
I am trying to simply return a single result from a query, that gets the price of some freight. So I can't turn this into an int because it must have decimals, hence trying to cast to a double. I am still learning asp.net so if there's a better way to achieve this, please do point me in the right direction :)
EDIT 2
the full code with SQL...
using (SqlCommand cmdCheck = new SqlCommand("SELECT FREIGHT_PRICE FROM FREIGHT_QUOTER_BELNL_NEW WHERE CUSTOMER_NO = #CUSTOMER_NO AND COUNTRY = #COUNTRY AND ROUND(WEIGHT_FROM,0) < #WEIGHT AND ROUND(WEIGHT_TO,0) >= #WEIGHT AND SHIPVIA = '48';", connection))
{
double collectionCharge = (double)cmdCheck.ExecuteScalar();
FreightAmount = collectionCharge;
}
The problem here is that ExecuteScalar is returning an int which is boxed into an object. In order to convert to a double you must first unbox to an int then convert to a double
double collectionCharge = (double)(int)cmdCheck.ExecuteScalar();
Use the Convert.ToXXX to avoid invalid cast exceptions.
I.E
collectionCharge=Convert.ToDouble(cmdCheck.ExecuteScalar());
As it appears that ExecuteScalar returns an Object so the code:
double collectionCharge = (double)cmdCheck.ExecuteScalar();
Could still fail
With thanks to #DJKRAZE.
I updated my query to SELECT CASE(FREIGHT_PRICE AS FLOAT) which now works with the (double) cast.
double collectionCharge = (double)cmdCheck.ExecuteScalar();
After reading all answers, I had a case of receiving the Decimal values indeed, and the solution was easy!
I just declared the function as string and received the Decimal value as string!
public static string Sals_AccountExpensesGetSums(int accountID)
{
SqlParameterHelper sph = new
SqlParameterHelper(ConnectionString.GetWriteConnectionString(),
"sals_AccountExpenses_GetAllSums", 1);
sph.DefineSqlParameter("#AccountID", SqlDbType.Int, ParameterDirection.Input, accountID);
string res = sph.ExecuteScalar().ToString();
return res;
}
and in the business layer i changed the result to double!
public static decimal GetAccountExpensesSums(int accountId)
{
string res = "";
decimal sums = 0;
res = DBAccount.Sals_AccountExpensesGetSums(accountId);
// check so we will not have exception
if ( res != "")
sums = Convert.ToDecimal(res);
return sums;
}
and the result was perfect as needed: 889678.70
I would recommend using this code:
object o = c.ExecuteScalar();
if (o != null)
{
int x = Int32.Parse(o.ToString());
}
This does two things. First it makes sure that your c.ExecuteScalar() isn't returning null If it did so and you tried to cast, you'd have problems.
Second, it makes casting much simpler because it can be applied to pretty much all cases when reading from a query.
The object becomes a string. If you want it as a string, you're done.
If you want it as a boolean, check to see if that string.Equals("true")
If you want it as an int, Int32.Parse(string);
if you want it as a long, Int64.Parse(string);
Basically, you won't have to worry about fully understanding overloading/explicit conversion.

C# int- or object-to-double casting error explanation

The below code fails at the last assignment:
static void Main(string[] args)
{
int a = 5;
object b = 5;
System.Diagnostics.Debug.Assert( a is int && b is int );
double x = (double)a;
double y = (double)b;
}
If both a and b are int, what is the cause of this error?
This is an extremely frequently asked question. See https://ericlippert.com/2009/03/03/representation-and-identity/ for an explanation.
Snippet:
I get a fair number of questions about the C# cast operator. The most frequent question I get is:
short sss = 123;
object ooo = sss; // Box the short.
int iii = (int) sss; // Perfectly legal.
int jjj = (int) (short) ooo; // Perfectly legal
int kkk = (int) ooo; // Invalid cast exception?! Why?
Why? Because a boxed T can only be unboxed to T. (*) Once it is unboxed, it’s just a value that can be cast as usual, so the double cast works just fine.
(*) Or Nullable<T>.
Unboxing requires the exact type - you can do this instead:
double y = (double)(int)b;
This is one of the rare cases where System.Convert comes in handy. You can use System.Convet.ToDouble(obj) to knock it out if you don't know before hand that it will be int.
Implicit casting is a compile-time operation. It's not possible for b of type object.
a is an int, but b is a reference to an object that is an int - it is what is called a boxed int. They are two different things, hence the different behaviors.

Categories

Resources