# How to take the average of two uint256s without overflowing?

Say you have two uint256 numbers, x, and y. One way to calculate the arithmetic average between them is this:

function avg(uint256 x, uint256 y) external returns (uint256 result) {
result = (x + y) / 2;
}


But this doesn't work when the intermediate result x + y does not fit into uint256.

A seemingly better approach is the following:

function avg(uint256 x, uint256 y) external returns (uint256 result) {
result = x / 2 + y / 2;
}


This doesn't overflow, but it doesn't work when both x and y are odd numbers - the 0.5 remainder is lost twice. Actually, if you'd prefer to round up the result, this doesn't work if either of x or y is an odd number.

How to take the average of two uint256 numbers in Solidity without overflowing?

• When x <= y the average can be calculated as x + (y - x) / 2.
– Ismael
Mar 29, 2021 at 16:24

After posting the question, I realised I gave the answer myself.

I simply have to check if both x and y are odd numbers and, if yes, add 1 to the result:

function avg(uint256 x, uint256 y) external returns (uint256 result) {
result = x / 2 + y / 2;
if (x % 2 == 1 && y % 2 == 1) {
result += 1;
}
}


Update: I ended up optimising the function, since I found it rather expensive at ~210 gas. I wrapped the code in an unchecked block, used the bitwise operator AND instead of the MOD operation and finally applied De Morgan's law:

function avg(uint256 x, uint256 y) external view returns (uint256 result) {
unchecked {
result = (x >> 1) + (y >> 1);
if (!(x & 1 == 0 || y & 1 == 0)) {
result += 1;
}
}
}


Which reduced the cost to ~82 gas.

2nd Update: I managed to save even more gas by getting rid of the if block:

function avg(uint256 x, uint256 y) external view returns (uint256 result) {
unchecked {
result = (x >> 1) + (y >> 1) + (x & y & 1);
}
}


Which reduced the gas cost to ~60.