如何仅使用加减运算求解自然数的平方根?技术实现咨询
Got it, let's break this down! Since we can only use addition and subtraction to find the square root of a natural number, we can lean on a clever mathematical property to make this work—no fancy built-in functions like sqrt() allowed.
Here's the key trick: the sum of the first n odd integers equals n². For example:
- 1 = 1²
- 1 + 3 = 4 = 2²
- 1 + 3 + 5 = 9 = 3²
- 1 + 3 + 5 + 7 = 16 = 4²
So to find the integer square root of a natural number x, we just keep subtracting consecutive odd numbers starting from 1 until we can't subtract anymore without going negative. The number of successful subtractions gives us the integer part of the square root.
Here's the C function implementation:
int integer_sqrt(int x) { // Guard clause: input is a natural number, so x < 0 is invalid if (x < 0) return -1; int root = 0; int current_odd = 1; while (x >= current_odd) { x -= current_odd; root++; current_odd += 2; // Move to the next odd number } return root; }
How it works:
- For
x = 16: We subtract 1, 3, 5, 7 (four times) untilxbecomes 0. Return4(exact square root). - For
x = 17: After subtracting the same four odds,xis left with 1 (can't subtract the next odd, 9). Return4(the integer part of √17).
If you need a decimal approximation instead of just the integer part, we can extend the same logic by scaling the input. For example, to get a result accurate to 2 decimal places:
- Multiply the input
xby10000(since10^4 = (10^2)^2—scaling by 100 for each decimal place, squared to keep the square root relationship). - Compute the integer square root of this scaled value.
- Divide the result by
100to convert back to a decimal.
Here's the code for this:
#include <stdio.h> int integer_sqrt(long long x) { if (x < 0) return -1; int root = 0; long long current_odd = 1; while (x >= current_odd) { x -= current_odd; root++; current_odd += 2; } return root; } double sqrt_approx(int x) { int int_root = integer_sqrt(x); // Check if x is a perfect square to avoid unnecessary scaling if ((long long)int_root * int_root == x) { return (double)int_root; } // Scale x to get 2 decimal places of precision long long scaled_x = (long long)x * 10000; int scaled_root = integer_sqrt(scaled_x); return (double)scaled_root / 100.0; } // Example usage int main() { printf("√16 = %.2f\n", sqrt_approx(16)); // Output: 4.00 printf("√17 = %.2f\n", sqrt_approx(17)); // Output: 4.12 printf("√2 = %.2f\n", sqrt_approx(2)); // Output: 1.41 return 0; }
Notes:
- We switched to
long longfor the scaled values to avoid integer overflow with larger inputs. - To get more decimal places, just adjust the scaling factor: for 3 decimal places, multiply by
1000000(10^6) and divide by1000.
- x = 0: The function returns 0, which is correct (√0 = 0).
- x = 1: Returns 1, which is exact.
- Large values: Using
long longensures we handle bigger natural numbers without overflow.
内容的提问来源于stack exchange,提问作者ProgrammingEnthusiast

