Most Arduino platforms don't have a floating-point unit ("FPU") and limited-enough memory to avoid implementing it in software. Often enough, we need to calculate a square root. There are many algorithms floating around on the internet, and I've tried several and give the following one my endorsement:
uint32_t sqrt(uint32_t number)
{
if (number == 0)
return 0UL;
if (number < 3)
return 1UL;
uint32_t x = number;
uint32_t y = 1;
int32_t error = 1;
while (x - y > error)
{
x = (x + y + 1) / 2; // half-up rounding with integers
y = (number + x / 2) / x;
}
return x;
}
It's based on the Babylonian/Newtonian method, and I've tweaked it so that the answer is "half-up" rounded instead of the usual integer truncation (rounding towards zero). Feel free to change it to whatever integer data type you're using. It won't work for floats -- you'll have to remove the rounding tricks. The trick is "(numerator + denominator/2)/denominator". You can speed up the loop at the expense of accuracy by increasing the allowable error.
Yes, there are faster, better, algorithms, but this one is simple enough to understand intuitively, and as such can be more easily debugged.
The Landing is a social site for Athabasca University staff, students and invited guests. It is a space where they can share, communicate and connect with anyone or everyone.
Unless you are logged in, you will only be able to see the fraction of posts on the site that have been made public. Right now you are not logged in.
If you have an Athabasca University login ID, use your standard username and password to access this site.
We welcome comments on public posts from members of the public. Please note, however, that all comments made on public posts must be moderated by their owners before they become visible on the site. The owner of the post (and no one else) has to do that.
If you want the full range of features and you have a login ID, log in using the links at the top of the page or at https://landing.athabascau.ca/login (logins are secure and encrypted)
Posts made here are the responsibility of their owners and may not reflect the views of Athabasca University.
Comments
Thanks Tyler. Great find. What is uint32_t? I think I saw that in your prior code too, if I'm correct.
uint32_t is a 32-bit unsigned integer data type as defined in the AVR version of inttypes.h (a common C/C++ library), part of the Arduino core:
Both links describe the same thing, but one is by Atmel (Microchip, nowadays) and the other by AVR Libc. Not actually sure which one of them is responsible for it.
The common Arduino equivalent on the Arduino Uno is unsigned long. I like using inttypes.h because it explicitly sets the word length (32-bits, in this example), whereas the word length may change if using the Arduino language. An easy example is double: it's 4 bytes on Arduinos that use ATmega chips (e.g. Uno), but 8 bytes on those with 32-bit chips (e.g. Due).