The problem is that the pow
function is unfortunately only specified for floating point numbers. And floating point numbers have inaccuracy, see this.
So when you do 2^2 you might not get exactly 4, but perhaps 3.9999. That's the actual bug. Then 3.9999 - 1 is 2.9999. When you convert this back to an integer type to print it on the port, it will get truncated to 2.
Now as it happens you shouldn't use floating point to begin with, as using floating point numbers in embedded systems is almost always bad design. Only programs that use floating point calculations extensively should need them. For example if you do lots of trigonometry calculations, signal processing, fuzzy logic, AI or similar special-case applications.
In which case you picked the wrong MCU entirely, as an 8 bit MCU with no FPU on chip will be extremely ineffective at processing such calculations! It isn't a PC.
Just forget about float numbers. It is trivial to write an integer version of pow() yourself:
uint32_t intpow (uint32_t base, uint32_t exp)
{
uint32_t sum;
if(exp == 0)
{
sum = 1;
}
else
{
sum = base;
for(uint32_t i=1; i<exp; i++)
{
sum *= base;
}
}
return sum;
}
In case you don't need large numbers, you can optimize the above quite a bit by going down to uint16_t
or uint8_t
, which your 8-bitter MCU will enjoy far more. And as noted in other answers, anything 2^x
could be solved with bit shifts.
Also, as mentioned in another answer, consider using look-up tables with pre-calculated values instead, if that's an option.
pow
is a function returning a floating point type. PORTx is an integer type. So you are getting a rounding error. \$\endgroup\$