Calculating an average (also known as the mean) sounds simple – but in C#, how you calculate it depends on:
- what type of numbers you have,
- where the numbers come from (arrays, lists, LINQ queries, streams),
- whether you need rounding,
- overflow protection,
- high-precision decimal accuracy,
- performance on large datasets.
This guide explains every way to compute averages in C#, from beginner basics to advanced numerical techniques used in finance, game dev, machine learning, and high-performance systems.
1. What Does “Average” Mean in Programming?
The average (arithmetic mean) is:
sum of all numbers ÷ count of numbers
Example:
Values = { 2, 4, 6, 8 }
Average = (2 + 4 + 6 + 8) / 4 = 5
Every method in this guide is based on that simple rule – only the implementation differs.
2. The Easiest Method: Using LINQ.Average()
⭐ Best for: beginners, readability, quick code
❌ Not ideal for: systems needing maximum performance
int[] numbers = { 2, 4, 6, 8 };
double avg = numbers.Average();
How it works internally:
- Iterates once through the sequence
- Computes the sum
- Computes the count
- Returns a
double, even if input is integers - Throws
InvalidOperationExceptionif the sequence is empty
Why it’s great:
✔ 1 line
✔ Readable
✔ Works with any numeric type
✔ Works with projections (.Average(x => x.Price))
3. Full Manual Calculation (Best for Learning)
int[] nums = { 2, 4, 6, 8 };
double sum = 0;
for (int i = 0; i < nums.Length; i++)
{
sum += nums[i];
}
double average = sum / nums.Length;
What this teaches:
- How sums accumulate
- Why we cast to
double - Why
sumis NOT anint - Dividing two integers does integer division (avoid!)
4. Avoiding Integer Division Bugs
If you do:
int avg = sum / count;
You will get integer division (truncates decimals):
int sum = 5;
int count = 2;
int avg = sum / count; // 2, not 2.5
Fix it by casting:
double avg = (double)sum / count;
5. Handling Empty Collections Safely
LINQ version
double avg = numbers.Any() ? numbers.Average() : 0;
Manual version
if (numbers.Length == 0)
return 0;
Choose your own “empty value” (0, null, nullable double, etc.).
6. Using decimal for Finance (HIGH Precision)
double is fast but has floating-point rounding issues.
If you’re doing:
- currency
- financial calculations
- invoicing
- VAT percentages
Use decimal.
decimal[] values = { 10.25m, 20.25m, 30.25m };
decimal avg = values.Average();
LINQ performs a decimal-aware average automatically.
7. Performance-Optimised Average (Large Datasets)
For millions of numbers, reduce allocations and improve CPU cache performance:
double AverageFast(int[] numbers)
{
long sum = 0; // prevents overflow
int count = numbers.Length;
for (int i = 0; i < count; i++)
sum += numbers[i];
return (double)sum / count;
}
Why long sum?
- Prevents overflow for large arrays
- Still very fast
- Avoids LINQ overhead
8. Using Span<T> for High-Performance Scenarios
double AverageSpan(ReadOnlySpan<int> span)
{
long sum = 0;
for (int i = 0; i < span.Length; i++)
sum += span[i];
return (double)sum / span.Length;
}
Why this is pro-level:
Span<T>avoids array-bound checking overhead- Zero heap allocations
- Perfect for game loops / real-time processing
9. Averaging With LINQ Projections (Real World)
Objects
var people = new[]
{
new { Name = "Eva", Age = 30 },
new { Name = "Tom", Age = 40 },
new { Name = "Sam", Age = 50 }
};
double avgAge = people.Average(p => p.Age);
Database rows
(When using Entity Framework, this becomes SQL AVG() automatically)
double avgPrice = db.Products.Average(p => p.Price);
10. Weighted Average (IMPORTANT for data science)
Not all items have equal importance.
Example: Test scores with weightings:
double WeightedAverage(int[] values, int[] weights)
{
double sum = 0;
double totalWeight = 0;
for (int i = 0; i < values.Length; i++)
{
sum += values[i] * weights[i];
totalWeight += weights[i];
}
return sum / totalWeight;
}
11. Streaming Average (Do NOT Load All Data)
Use this when you read numbers one by one from:
- files
- database streams
- telemetry
- IoT sensors
double sum = 0;
long count = 0;
foreach (var x in stream)
{
sum += x;
count++;
}
double avg = sum / count;
Why this matters:
- No array needed
- Memory usage stays tiny
12. Online Average (No Sum Overflow, Real Time)
This prevents overflow AND calculates average on the fly.
Formula (Welford’s Method):
double avg = 0;
long count = 0;
foreach (var value in values)
{
count++;
avg += (value - avg) / count;
}
Benefits:
✔ Best numerical stability
✔ Works with huge streams
✔ Never overflows
✔ Used in scientific computing
13. Using Aggregate() in LINQ (Functional Style)
double avg = numbers
.Aggregate(
new { Sum = 0.0, Count = 0 },
(acc, x) => new { Sum = acc.Sum + x, Count = acc.Count + 1 },
acc => acc.Sum / acc.Count
);
Not beginner-friendly but extremely expressive.
14. Parallel Average (PLINQ)
For extremely large numbers:
double avg = numbers
.AsParallel()
.Average();
Useful when:
- Millions of items
- Multi-core CPU
- Purely numeric data
15. Averaging Specific Parts of an Array
Average of first N items:
double avgFirst = numbers.Take(10).Average();
Average of last N items:
double avgLast = numbers.Skip(numbers.Length - 10).Average();
Average of even numbers only:
double avgEven = numbers.Where(n => n % 2 == 0).Average();
16. Rounding the Average
Round to 2 decimals:
double rounded = Math.Round(avg, 2);
Round down:
double down = Math.Floor(avg);
Round up:
double up = Math.Ceiling(avg);
Banker’s rounding:
Math.Round(avg, 2, MidpointRounding.ToEven);
Which Method Should You Use?
✔ Easiest
numbers.Average()
✔ Most readable
numbers.Average(x => x.Value)
✔ Best performance
Manual loop with long sum
✔ Zero-allocation
Span<T> method
✔ Best for financial accuracy
decimal + LINQ
✔ Best for big-data
Streaming / online average
✔ Best for multi-core
PLINQ .AsParallel().Average()