C# Keeps Rounding Numbers Up Producing inaccurate results - c#

Ok so this is doing my head in, it keeps producing a slightly inaccurate result by rounding up the digits after the decimal. i need the exact value, not a rounded one!
So to start with take the following code:
int num1 = 10087;
int num2 = 9971;
int num3 = 9909;
int num4 = 9917;
int num5 = 9904;
double average = (num1 + num2 + num3 + num4 + num5) / 5;
double percentage = (10000 - average) / 100;
If this math is done on a calculator, the value of "percentage" is 0.424. But if it is run through the code the value gets rounded to 0.43 which is inaccurate. How can i stop this happening?
note: please do not question the 10000 number, i also need the result to be exactly the correct number (0.424) that is very important in this case!

cast your average calc to double first
int num1 = 10087;
int num2 = 9971;
int num3 = 9909;
int num4 = 9917;
int num5 = 9904;
double average = (double)(num1 + num2 + num3 + num4 + num5) / 5;
double percentage = (10000 - average) / 100;

Just add a "d" after the numbers...
int num1 = 10087;
int num2 = 9971;
int num3 = 9909;
int num4 = 9917;
int num5 = 9904;
double average = (num1 + num2 + num3 + num4 + num5) / 5d;
double percentage = (10000 - average) / 100d;
The d tells the compiler to make these numbers double precision floating point values instead of integers (you can also just add a decimal point). Without the "d" the numbers are integers and the computer performs integer arithmetic. This means that
9 / 5 = 1 instead of 1.8

Kindly read the msdn form it will help you to know the real reason
reference :- http://msdn.microsoft.com/en-us/library/3b1ff23f.aspx
In it they already say that
When you divide two integers, the result is always an integer
Here you divide two integer so it's result is also int.
You just need to type cast that's all as the other people give ans
As Ela Write your code will look like
int num1 = 10087;
int num2 = 9971;
int num3 = 9909;
int num4 = 9917;
int num5 = 9904;
double average = (double)(num1 + num2 + num3 + num4 + num5) / 5;
double percentage = (10000 - average) / 100;

Related

How can I have a double value using Math.DivRem()?

I can't show the double values in C#
Math.DivRem(double money, int number, out int remain);
Math.DivRem Method is only compatible with Int64 and Int32, which means you can't use double, float or any numeric data type with decimals.
Depending on what you are looking for, this is two other methods of getting the quotient and remainder of your doubles:
double a = 20.1;
double b = 4.93;
double remainder = a % b; // Returns 0.380...
double quotient = a / b; // Returns 4,077...
If you want to make your remainder or quotient to an int, just use
int result = Convert.ToInt32(quotient); // Returns 4
Or to make it more efficient
int result = ConvertToInt32(a / b); // Returns 4
EDIT
One workaround to use Math.DivRem with "doubles", are by multiplying both sides with a constant, for example 100 000. After getting the remainder, divide it with the constant.
double money = 5.515;
int number = 2;
int constant = 100000;
Math.DivRem(Convert.ToInt32(money * constant), number * constant, out int remain);
// Divides 551500 with 200000
// remain = 151500
// For double
double d = (double) remain / (double) constant; // Return 1,515
// For int
remain /= constant; // Return 1
DOUBLE EDIT
Use this instead of Math.DivRem() when dealing with doubles and ints combined.
double money = 12.15;
int number = 5;
double remainder = money % number; // Return 2,15...
int remainder = (int)(money % number); // Return 2

Average of 3 long integers

I have 3 very large signed integers.
long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
I want to calculate their truncated average. Expected average value is long.MaxValue - 1, which is 9223372036854775806.
It is impossible to calculate it as:
long avg = (x + y + z) / 3; // 3074457345618258600
Note: I read all those questions about average of 2 numbers, but I don't see how that technique can be applied to average of 3 numbers.
It would be very easy with the usage of BigInteger, but let's assume I cannot use it.
BigInteger bx = new BigInteger(x);
BigInteger by = new BigInteger(y);
BigInteger bz = new BigInteger(z);
BigInteger bavg = (bx + by + bz) / 3; // 9223372036854775806
If I convert to double, then, of course, I lose precision:
double dx = x;
double dy = y;
double dz = z;
double davg = (dx + dy + dz) / 3; // 9223372036854780000
If I convert to decimal, it works, but also let's assume that I cannot use it.
decimal mx = x;
decimal my = y;
decimal mz = z;
decimal mavg = (mx + my + mz) / 3; // 9223372036854775806
Question: Is there a way to calculate the truncated average of 3 very large integers only with the usage of long type? Don't consider that question as C#-specific, just it is easier for me to provide samples in C#.
This code will work, but isn't that pretty.
It first divides all three values (it floors the values, so you 'lose' the remainder), and then divides the remainder:
long n = x / 3
+ y / 3
+ z / 3
+ ( x % 3
+ y % 3
+ z % 3
) / 3
Note that the above sample does not always work properly when having one or more negative values.
As discussed with Ulugbek, since the number of comments are exploding below, here is the current BEST solution for both positive and negative values.
Thanks to answers and comments of Ulugbek Umirov, James S, KevinZ, Marc van Leeuwen, gnasher729 this is the current solution:
static long CalculateAverage(long x, long y, long z)
{
return (x % 3 + y % 3 + z % 3 + 6) / 3 - 2
+ x / 3 + y / 3 + z / 3;
}
static long CalculateAverage(params long[] arr)
{
int count = arr.Length;
return (arr.Sum(n => n % count) + count * (count - 1)) / count - (count - 1)
+ arr.Sum(n => n / count);
}
NB - Patrick has already given a great answer. Expanding on this you could do a generic version for any number of integers like so:
long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
long[] arr = { x, y, z };
var avg = arr.Select(i => i / arr.Length).Sum()
+ arr.Select(i => i % arr.Length).Sum() / arr.Length;
Patrick Hofman has posted a great solution. But if needed it can still be implemented in several other ways. Using the algorithm here I have another solution. If implemented carefully it may be faster than the multiple divisions in systems with slow hardware divisors. It can be further optimized by using divide by constants technique from hacker's delight
public class int128_t {
private int H;
private long L;
public int128_t(int h, long l)
{
H = h;
L = l;
}
public int128_t add(int128_t a)
{
int128_t s;
s.L = L + a.L;
s.H = H + a.H + (s.L < a.L);
return b;
}
private int128_t rshift2() // right shift 2
{
int128_t r;
r.H = H >> 2;
r.L = (L >> 2) | ((H & 0x03) << 62);
return r;
}
public int128_t divideby3()
{
int128_t sum = {0, 0}, num = new int128_t(H, L);
while (num.H || num.L > 3)
{
int128_t n_sar2 = num.rshift2();
sum = add(n_sar2, sum);
num = add(n_sar2, new int128_t(0, num.L & 3));
}
if (num.H == 0 && num.L == 3)
{
// sum = add(sum, 1);
sum.L++;
if (sum.L == 0) sum.H++;
}
return sum;
}
};
int128_t t = new int128_t(0, x);
t = t.add(new int128_t(0, y));
t = t.add(new int128_t(0, z));
t = t.divideby3();
long average = t.L;
In C/C++ on 64-bit platforms it's much easier with __int128
int64_t average = ((__int128)x + y + z)/3;
You can calculate the mean of numbers based on the differences between the numbers rather than using the sum.
Let's say x is the max, y is the median, z is the min (as you have). We will call them max, median and min.
Conditional checker added as per #UlugbekUmirov's comment:
long tmp = median + ((min - median) / 2); //Average of min 2 values
if (median > 0) tmp = median + ((max - median) / 2); //Average of max 2 values
long mean;
if (min > 0) {
mean = min + ((tmp - min) * (2.0 / 3)); //Average of all 3 values
} else if (median > 0) {
mean = min;
while (mean != tmp) {
mean += 2;
tmp--;
}
} else if (max > 0) {
mean = max;
while (mean != tmp) {
mean--;
tmp += 2;
}
} else {
mean = max + ((tmp - max) * (2.0 / 3));
}
Patching Patrick Hofman's solution with supercat's correction, I give you the following:
static Int64 Avg3 ( Int64 x, Int64 y, Int64 z )
{
UInt64 flag = 1ul << 63;
UInt64 x_ = flag ^ (UInt64) x;
UInt64 y_ = flag ^ (UInt64) y;
UInt64 z_ = flag ^ (UInt64) z;
UInt64 quotient = x_ / 3ul + y_ / 3ul + z_ / 3ul
+ ( x_ % 3ul + y_ % 3ul + z_ % 3ul ) / 3ul;
return (Int64) (quotient ^ flag);
}
And the N element case:
static Int64 AvgN ( params Int64 [ ] args )
{
UInt64 length = (UInt64) args.Length;
UInt64 flag = 1ul << 63;
UInt64 quotient_sum = 0;
UInt64 remainder_sum = 0;
foreach ( Int64 item in args )
{
UInt64 uitem = flag ^ (UInt64) item;
quotient_sum += uitem / length;
remainder_sum += uitem % length;
}
return (Int64) ( flag ^ ( quotient_sum + remainder_sum / length ) );
}
This always gives the floor() of the mean, and eliminates every possible edge case.
Because C uses floored division rather than Euclidian division, it may easier to compute a properly-rounded average of three unsigned values than three signed ones. Simply add 0x8000000000000000UL to each number before taking the unsigned average, subtract it after taking the result, and use an unchecked cast back to Int64 to get a signed average.
To compute the unsigned average, compute the sum of the top 32 bits of the three values. Then compute the sum of the bottom 32 bits of the three values, plus the sum from above, plus one [the plus one is to yield a rounded result]. The average will be 0x55555555 times the first sum, plus one third of the second.
Performance on 32-bit processors might be enhanced by producing three "sum" values each of which is 32 bits long, so that the final result is ((0x55555555UL * sumX)<<32) + 0x55555555UL * sumH + sumL/3; it might possibly be further enhanced by replacing sumL/3 with ((sumL * 0x55555556UL) >> 32), though the latter would depend upon the JIT optimizer [it might know how to replace a division by 3 with a multiply, and its code might actually be more efficient than an explicit multiply operation].
If you know you have N values, can you just divide each value by N and sum them together?
long GetAverage(long* arrayVals, int n)
{
long avg = 0;
long rem = 0;
for(int i=0; i<n; ++i)
{
avg += arrayVals[i] / n;
rem += arrayVals[i] % n;
}
return avg + (rem / n);
}
You could use the fact that you can write each of the numbers as y = ax + b, where x is a constant. Each a would be y / x (the integer part of that division). Each b would be y % x (the rest/modulo of that division). If you choose this constant in an intelligent way, for example by choosing the square root of the maximum number as a constant, you can get the average of x numbers without having problems with overflow.
The average of an arbitrary list of numbers can be found by finding:
( ( sum( all A's ) / length ) * constant ) +
( ( sum( all A's ) % length ) * constant / length) +
( ( sum( all B's ) / length )
where % denotes modulo and / denotes the 'whole' part of division.
The program would look something like:
class Program
{
static void Main()
{
List<long> list = new List<long>();
list.Add( long.MaxValue );
list.Add( long.MaxValue - 1 );
list.Add( long.MaxValue - 2 );
long sumA = 0, sumB = 0;
long res1, res2, res3;
//You should calculate the following dynamically
long constant = 1753413056;
foreach (long num in list)
{
sumA += num / constant;
sumB += num % constant;
}
res1 = (sumA / list.Count) * constant;
res2 = ((sumA % list.Count) * constant) / list.Count;
res3 = sumB / list.Count;
Console.WriteLine( res1 + res2 + res3 );
}
}
I also tried it and come up with a faster solution (although only by a factor about 3/4). It uses a single division
public static long avg(long a, long b, long c) {
final long quarterSum = (a>>2) + (b>>2) + (c>>2);
final long lowSum = (a&3) + (b&3) + (c&3);
final long twelfth = quarterSum / 3;
final long quarterRemainder = quarterSum - 3*twelfth;
final long adjustment = smallDiv3(lowSum + 4*quarterRemainder);
return 4*twelfth + adjustment;
}
where smallDiv3 is division by 3 using multipliation and working only for small arguments
private static long smallDiv3(long n) {
assert -30 <= n && n <= 30;
// Constants found rather experimentally.
return (64/3*n + 10) >> 6;
}
Here is the whole code including a test and a benchmark, the results are not that impressive.
This function computes the result in two divisions. It should generalize nicely to other divisors and word sizes.
It works by computing the double-word addition result, then working out the division.
Int64 average(Int64 a, Int64 b, Int64 c) {
// constants: 0x10000000000000000 div/mod 3
const Int64 hdiv3 = UInt64(-3) / 3 + 1;
const Int64 hmod3 = UInt64(-3) % 3;
// compute the signed double-word addition result in hi:lo
UInt64 lo = a; Int64 hi = a>=0 ? 0 : -1;
lo += b; hi += b>=0 ? lo<b : -(lo>=UInt64(b));
lo += c; hi += c>=0 ? lo<c : -(lo>=UInt64(c));
// divide, do a correction when high/low modulos add up
return hi>=0 ? lo/3 + hi*hdiv3 + (lo%3 + hi*hmod3)/3
: lo/3+1 + hi*hdiv3 + Int64(lo%3-3 + hi*hmod3)/3;
}
Math
(x + y + z) / 3 = x/3 + y/3 + z/3
(a[1] + a[2] + .. + a[k]) / k = a[1]/k + a[2]/k + .. + a[k]/k
Code
long calculateAverage (long a [])
{
double average = 0;
foreach (long x in a)
average += (Convert.ToDouble(x)/Convert.ToDouble(a.Length));
return Convert.ToInt64(Math.Round(average));
}
long calculateAverage_Safe (long a [])
{
double average = 0;
double b = 0;
foreach (long x in a)
{
b = (Convert.ToDouble(x)/Convert.ToDouble(a.Length));
if (b >= (Convert.ToDouble(long.MaxValue)-average))
throw new OverflowException ();
average += b;
}
return Convert.ToInt64(Math.Round(average));
}
Try this:
long n = Array.ConvertAll(new[]{x,y,z},v=>v/3).Sum()
+ (Array.ConvertAll(new[]{x,y,z},v=>v%3).Sum() / 3);

Quotients to 2 Decimal places

So I need to get a quotient to 2 decimal places like 0.33, but do I need to use doubles all the way down or can I use integers for everything except the quotient and then just use double or decimal for the quotient? It is also breaking because of the quotient. If anyone could help me I would be extremely grateful :)
int firstnumber;
int secondnumber;
decimal quotient;
firstnumber = int.Parse(inputTextBox1.Text);
secondnumber = int.Parse(inputTextBox2.Text);
sumLabel.Text = (firstnumber + secondnumber).ToString();
differenceLabel.Text = (firstnumber - secondnumber).ToString();
productLabel.Text = (firstnumber * secondnumber).ToString();
quotient = decimal.Parse(quotientLabel.Text);
quotient = (firstnumber / secondnumber).tostring;
You can cast the integers to decimal or double when assigning your variable, then assign the label from the results:
quotient = ((decimal)firstnumber / secondnumber);
quotientLabel.Text = quotient.ToString("N2");

I'm having an issue calculating the Greatest common divisor [C# with VS 2012]

I have to write 2 different numbers in two textboxes, and with a button calculate the GCD, but when I run it, the button does nothing.
int x = Convert.ToInt16(txtNum1.Text);
int y = Convert.ToInt16(txtNum2.Text);
int num1, num2;
int residuo;
if (x < y)
{
num1 = y;
num2 = x;
}
else
{
num1 = x;
num2 = y;
}
do
{
residuo = num1 % num2;
if (residuo == 0)
{
txtMCD.Text = num2.ToString();
}
else
{
num1 = num2;
num2 = residuo;
}
} while (residuo == 0);
X and y are both numbers writen in the textboxes, I use num1 and num2 to save the value of x and y in order that num1 is the higher, and num2 the lesser. Any ideas?
Your termination condition is incorrect. It should be while (residuo != 0). As it is, you either terminate the loop after one iteration, or you are in an infinte loop.

Quotient in Windows phone 7 + silverlight + C#

Is there any inbuilt function to get quotient of a division. Math.DivRem is not appplicable it seems.
Division of integer operands will yield the integer quotient. If your inputs are floating point types, just first convert them to integer types:
double num1 = 27;
int num2 = 7;
double dblResult = num1 / num2; // will yield floating point result 3.857...
int intResult =(int)num1 / num2; // will yield integer quotient 3

Categories

Resources