Int64 arithmetic error - c#

Why is the output "0 and 0"? How do I fix it?
Int64 small= (long)0.25 * (long)Int64.MaxValue;
Int64 large = (long)0.75 * (long)Int64.MaxValue;
System.Console.WriteLine(small + " and " + large);
System.Console.ReadLine();
//output
//0 and 0

Statement (long)0.75 will return 0 (converting double to long will take greatest integer value, that is lower that converting double). So you have 0 * 9223372036854775807 which is hopefully 0. By the way long is alias for Int64, which means they are the same underlying types, so by (long)Int64.MaxValue you casting long to long
to fix it simply use double * long multiplication
long small= (long)(0.25 * long.MaxValue);
long large = (long)(0.75 * long.MaxValue);
Console.WriteLine ("{0:N}", small); //print 2,305,843,009,213,693,952.00
Console.WriteLine ("{0:N}", large); //print 6,917,529,027,641,081,856.00
don't bother with "{0:N}" literal, it's simply a format to give the output some visual beauty. By default double is printed in scientific notation, which is not so demonstrable (for example 2.30584300921369E+18 for first operation)

The reason why is that in both cases you are converting a value which is less than 1 to a long. This will truncate the value to 0 hence the multiplication also results in 0
Console.WriteLine((long)0.25); // 0
Console.WriteLine((long)0.75); // 0

Because 0.25 and 0.75 casted as long are 0.
In order to remedy that, you will need to use floats or doubles. However, I'm not 100% certain the precision is enough to lead to exact results:
Int64 small= (Int64)(0.25 * (double)Int64.MaxValue);
Int64 large = (Int64)(0.75 * (double)Int64.MaxValue);

You want to convert after not before the multiplication. Try
Int64 small= (long) (0.25 * (double) Int64.MaxValue);
Before you were converting .25 to long which is 0.

Related

Cannot calculate Long Data type in C#

I do not know why am I getting output as 0. Please help me to figure out my mistake in correcting the calculation for the long data type in C#. I have almost all variables in long to make it easier, but even then, the code does not work as expected.
long data_user;
long GB;
long MB;
long kB;
long bits;
long bits_rem;
double giga_C;
double mega_c;
double kilo_C;
double byte_C;
double sub_tot;
Console.Write("\nEnter the number of bytes used: ");
data_used = Console.Read();
//Divide data into each units.
GB = data_user / 1073741824;
giga_C = Convert.ToDouble(15.00 * GB);
MB = bits_rem / 1045214;
mega_C = (6.05 * MB);
kB = bits_rem / 10002;
kilo_C = (3.50 * kB);
bits = bits_rem / 0.1;
bits_C = (0.01 * bits);
sub_tot = (giga_C + mega_C + kilo_C + byte_C);
Console.Read reads the next character from the Console, so that you always get smaller number divided by big one (which is zero in integer arithmetic). For example, you write 1234, but Console.Read returns 49 because Unicode point for '1' is 49. Then you try to divide 49 by 1073741824 and obviously get 0.
You need to read your value as following Convert.ToInt64(Console.ReadLine())

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 calculate a percentage

I want to calculate a percentage. My code is:
Bot.Log("[ KEYBOT ] The total is " + (suctrades * totaltrades ) / 100 + "% !");
If I do this, I only get 0. What am I doing wrong?
Probably suctrades * totaltrades is still an int. The easiest way will be probably changing your code to:
((double)suctrades) * totaltrades/100
Or
suctrades * totaltrades/100.0
To force using double instead of int
Try :
Bot.Log("[ KEYBOT ] The total is " + ((double)suctrades * totaltrades ) / 100 + "% !");
I assume suctrades and totaltrades are not of decimal type. This should fix this due to type propagation as expression is evaluated.
Int is an integer type; dividing two ints performs an integer division, i.e. the fractional part is truncated since it can't be stored in the result type (also int!). Decimal, by contrast, has got a fractional part. By invoking Decimal.Divide, your int arguments get implicitly converted to Decimals.
You can enforce non-integer division on int arguments by explicitly casting at least one of the arguments to a floating-point type, e.g.: 100.0m this is casting to decimal !
decimal result = suctrades * totaltrades/100.0m

High(ish) presision math on decimal

The Question:
I am using Visual C# Express 2010. I am trying to divide three integers, however, the result is always 0.
My Code:
//earlier in the code:
int totalKeywords = 3;
//the problem code:
decimal onePercent = 100 / totalKeywords / 100; //100% divided by the number of keywords divided by 100 to make one percent
MessageBox.Show(onePercent);
//result: 0
//what I want: 0.33 or more acurate
What I've tried:
I've changed the value of totalKeywords
I've tried onePercent as a double, int, float, ect.
Guesses:
It could be that the built-in math doesn't work for some reason (WHY??)
It could be that decimal / int / float, etc. don't hold decimals (I don't think so)
My Efforts:
Google
Stack Overflow
C# high precision calculations
C# High double precision
etc.
Let's break it down:
decimal onePercent = 100 / totalKeywords / 100;
First, divide the integer literal 100 by the integer variable totalKeywords (value is 3). Result: integer 33.
Next, divide the result 33 by the integer literal 100. Result: integer 0.
The right-hand expression has type int, value 0. Convert that implicitly to the decmal 0m, so you can then assign that to the decimal variable onePercent.
Result: 0m.
To fix, as others have noticed, make the leftmost constant (if not all of them, for clarity) into a decimal. This will do, as the ints will implicitly convert to decimal:
decimal onePercent = 100m / totalKeywords / 100;
This is totally unambiguous, if a little over the top:
decimal onePercent = 100m / (decimal)totalKeywords / 100m;
try 100m / totalKeywords / 100
you have to define one of your numbers (at least) as decimal.
100 is an int
100m is a decimal
http://msdn.microsoft.com/en-us/library/364x0z75.aspx
If you want a numeric real literal to be treated as decimal, use the suffix m or M, for example:
decimal myMoney = 300.5m;
on right side after calculation you will get only integer, then it will be assigned to decimal, so it gives you 0.

Subtract percentage in C#

I'm trying to subtract percentage in C# using:
n = n - (n * 0.25);
but I'm getting an error:
"Cannot implicitly 'double' to 'int'. An explicit conversions exists
(are you missing a cast?)"
Your value n is an int.
When you multiply by 0.25( which is a double), the resulting value is a double that you try to assign to a int.
To solve it, you have to specify that you are aware that you will lose precision using "explicit conversion".
n = n - (int)(n * 0.25);
Doing (Type)value is called "to cast value to Type". This is exactly what the error message suggest you to do.
Or, if you don't want to keep the precision, declare n not as an int but as a double. In this case, you will not have to cast n * 0.25 to int.
If you don't want to switch back and forwards between int and double types you could just use:
n = (n * 75) / 100
if your answer ever has decimals they'll be lost though
Your variable n must be an integer, but the result of your calculation is a double, since it involves multiplication by a double (0.25).
You can cast the result back to an int like this:
n = (int)(n - (n * 0.25));
I'm assuming that n is an integer type then, say int, as you don't give a clue to that. In which case the easiest solution is to do:
n = Convert.ToInt32(n - (n * 0.25));
Or you can cast:
n = (int)(n - (n * 0.25));
Check the type of variable 'n'.
Either 'n' should be of double type.
Or
Use explicit cast to convert to int.
int n = (int)(n - (n * 0.25));
you must cast result to int
n=(int)(n-(n*0.25));
try:
n = n - (int)((double)n * 0.25);
note: by doing this you wont have numbers behind the point in the n result.
I guess this could be an issue with the type of n being int it least needs to be double
hence when you have n = n - (n * 0.25) the result is a double
if you want to cast it as int then beware of rounding since it would not always be ending in .00
Also i think this would be better n = n * 0.75
Your n variable is an int. When you try to multiple with 0.25, 0.25 is double, so result will be double. You should cast it manually because there is no Implicit Numeric Conversion for double to int. You have to use Explicit Numeric Conversion for them.
From --> To
double --> sbyte , byte, short, ushort, int, uint, long, ulong, char, float, or decimal
You should convert your right expression to int.
int n = 100;
n = (int) (n - (n * 0.25));
Console.WriteLine(n);
Here is a DEMO.
And remember;
Explicit numeric conversion may cause loss of precision.
When you convert from a double value to an integral type, the value is truncated. If the resulting integral value is outside the range of the destination value, the result depends on the overflow checking context.
The best way would be to do
n = n - n/4;
If you want a percentage to be a whole number between 0 and 100, otherwise you should declare n to be a double by replacing int n with double n.
No costly conversion will occur in the proposed assignment. Note that n/4 is an integer because both operands (n and 4) are integers, causing no promotions, thus using integer division.
Explanation
This is type promotion, n is multiplied by a double, which promotes n*0.25 automatically to a double. A primitive can only be promoted into a higher rank, not demoted to a lower rank. A primitive x is of a higher rank then another primitive y if it can hold all values of y without causing loss of precision. A double can hold all values of an integer, but an integer can, for example, not hold 0.1. So you are trying to promote and demote. See MSDN library for more information.
Note:
Casting from a double to an int causes the value to be truncated, that is all decimals after the 'dot' will be erased, so -2.5 becomes -2 and 1.5 becomes 1. Integer division, as used above also rounds to zero, making this assignment equal with your assignment. But avoiding any costly conversions.

Categories

Resources