问题
Recently, I came across a problem in someone's programming class. It asked them to compute a square root using only integers; they were to use one integer to represent the part before the decimal point and another integer to represent the part after the decimal point. The problem said that using floating point numbers was not allowed.
However, after thinking about it for some time, I can't seem to come up with a way of doing it without using floating point. I've Googled high and low and I can't seem to find an answer.
I jokingly suggested that my friend implement an FPU to do this, but he wasn't so amused.
Does anyone have any ideas about how to go about solving this?
回答1:
Let's say your original number is x
.
Finding part before decimal point is easy - just find the maximal number, which square is less or equal to the original number.
Multiply original number by 100 and the integer part of sqrt by 10. Add 1 to it until it's less or equal to
100x
. Do itn
times and divide by10^n
at the end to get the final answer truncated ton
decimal places.
回答2:
Assume you have an algorithm that creates two integers A
and B
so that the ratio A / B
gives you your desired approximation to the square root to the appropriate number of decimal places. Then, the two numbers you want will be:
- The integer part is
(A - (A % B)) / B
. - The fractional part: Let
X
beA % B
. Then the rationX / B
represents the fractional part. Then the computed fractional part is done by building the successive digits by computing(10*X - (10*X % B)) / B
and settingX = (10*X % B)
over and over again until you get the number of decimal places you want.
To derive the desired fraction approximation to your square root, you can compute a continued fraction for your square root.
回答3:
In pseudo-code it would be something like this:
int whole_ans = sqrt(num); //stores final answer integer part
int dec_ans; //stores final answer decimal part
int num_of_decimals = x //x is equal to the number of decimal places you want the answer to be
int targetNum = (num - (whole_ans^2)) * 100; //initialize target to residual * 100
int currAns = whole_ans; //initialize target to residual of num - the answer so far
for(int i=0;i<x;i++)
{
x = get_next_digit(targetNum,currAns));
dec_ans = append(dec_ans, x); //append the new found digit to the right of the current decimal answer
targetNum = (targetNum - (currAns * 20 + x) * x) * 100; //update target number to be residual + 2 zero digits
currAns = append(currAns,dec_ans) //append the decimal part of the answer to the current total answer so far
}
func get_next_digit(targetNum,currAns)
{
int attempt=0;
int i=0;
while(attempt <= targetNum)
{
i++;
attempt = (20 * currAns + i) * i;
}
i--;
return i;
}
This answer follows the steps on calculating a square root by hand: http://www.wikihow.com/Calculate-a-Square-Root-by-Hand
回答4:
Suppose you want to compute the square root of 123.4567.
Then all you have to do is shift the decimal point far enough to the right to get an integer radicand -- in this example, four places -- and so, the following is true:
sqrt(123.4567) = (1/100) * sqrt(1234567)
That is, all you need to know is how to find the square root of an integer. For this, consider the following code (in C):
unsigned int int_sqrt (unsigned int n) {
unsigned int result = 0;
unsigned int count = 1;
for (; count*count <= n; count += 1) {
result = result + 1;
}
return result;
}
If you want to do away with the multiplication, you can also do this:
unsigned int int_sqrt (unsigned int n) {
unsigned int result = 0;
unsigned int odd = 1;
unsigned int oddsum = 1;
while (oddsum <= n) {
result = result + 1;
odd = odd + 2;
oddsum = oddsum + odd;
}
return result;
}
These are clearly not the fastest ways to do it -- but they use integers only, and they do not rely on characteristics of particular CPUs such as word length.
回答5:
I believe a modified form of binary binary search is what will help you achieve that. Let me elaborate that in a pseudo code.
int square_number =findSquareRootFloor(GivenValue);
findSquareRootFloor( int number)
{
int low = 0;
int high = number;
while (low <=high)
{
int mid = number /2; // note use integer division
target = searchedValue * searchedValue`enter code here`;
if (target > number)
high = mid-1;
else if (target < number)
low = mid +1;
else
{ // exact match
return mid;
}
}
// if we have come here mid stores the floor of the square root
}
来源:https://stackoverflow.com/questions/16532697/finding-a-square-root-using-only-integers