嘿我怎样才能使用MIPS汇编找到整数的平方根?
答案 0 :(得分:5)
我们可以使用提交for this question的算法,并根据需要进行调整。在进入MIPS之前,让我们看看C:
中的实现//Function to compute sqroot(n)
int sqroot(int n) {
int x = n;
for (int i = 0; i < (n/2); i++)
x = (x + n / x) / 2;
return x;
}
sqroot(n)
函数将计算和整数等于n
的平方根的最低值。因此,如果你打电话给sqroot(225)
,你会得到预期的15,但sqroot(15)
会返回3而不是3.87298。
从C代码中,我们可以概述MIPS代码的外观:
In calling function:
Load the number to be squared into $a0
jal root
root:
Initialize $t0 = n, $t1 = i = 0, $t2 = x = n = $a0, $t3 = n/2
Loop:
Divide n/x
Add x to n/x
Divide (x + n/x) by 2
Check if $t1 < $t3
If it is, branch back to loop
Else, move x into return register $v0
请注意:
答案 1 :(得分:2)
当仅使用整数进行操作时,我发现Newton的方法x = (x + n/x) / 2
不能令人满意,因为终止条件很难准确计算。 n/2
只是猜测,几乎总是超过必要的迭代次数。牛顿方法收敛二次,与n
不成比例,而是sqrt(n)
。另一个建议,&#34;不断重复,直到x停止改变&#34;也不起作用,因为对于非完美的正方形x
将在根的地板和天花板之间交替 - 由于整数数学,当n/x
稍微小一点时,术语x
将交替出现或略大于sqrt(n)
。
我从wikipedia采用了逐位数字根计算方法,并创建了MIPS版本。它没有低效率(n/2
)或含糊不清(floor(sqrt(n))
或ceil(sqrt(n))
)。查找表方法可以更有效地返回结果,但假设查找表不可用,这是一种好的可靠方法。
首先,我将C示例翻译为仅使用小于(<
)比较,因为MIPS仅提供小于slt
的比较指令。
int isqrt(int num) {
int ret = 0;
int bit = 1 << 30; // The second-to-top bit is set
// "bit" starts at the highest power of four <= the argument.
while (num < bit) {
bit >>= 2;
}
while (bit != 0) {
if (num < ret + bit) {
ret >>= 1;
} else {
num -= ret + bit;
ret = (ret >> 1) + bit;
}
bit >>= 2;
}
return ret;
}
以下是生成的MIPS代码:
isqrt:
# v0 - return / root
# t0 - bit
# t1 - num
# t2,t3 - temps
move $v0, $zero # initalize return
move $t1, $a0 # move a0 to t1
addi $t0, $zero, 1
sll $t0, $t0, 30 # shift to second-to-top bit
isqrt_bit:
slt $t2, $t1, $t0 # num < bit
beq $t2, $zero, isqrt_loop
srl $t0, $t0, 2 # bit >> 2
j isqrt_bit
isqrt_loop:
beq $t0, $zero, isqrt_return
add $t3, $v0, $t0 # t3 = return + bit
slt $t2, $t1, $t3
beq $t2, $zero, isqrt_else
srl $v0, $v0, 1 # return >> 1
j isqrt_loop_end
isqrt_else:
sub $t1, $t1, $t3 # num -= return + bit
srl $v0, $v0, 1 # return >> 1
add $v0, $v0, $t0 # return + bit
isqrt_loop_end:
srl $t0, $t0, 2 # bit >> 2
j isqrt_loop
isqrt_return:
jr $ra
您可以像任何其他MIPS程序一样调用它:
addi $a0, $zero, 15
jal isqrt # v0 = result
此程序始终会为正面参数返回$v0 = floor(sqrt($a0))
。
小心:代码进入否定参数的无限循环。在调用此过程之前清理您的输入。
答案 2 :(得分:2)
它不是MIPS,而是汇编。我发现的基本算法是基于前n个奇数加在一起= n ^ 2的事实。
因此,如果您通过反转过程并从您想要取平方根的数字中减去它来利用它,您可以循环获得准确的答案或近似值。我认为非完美正方形的根+ 1。
这个想法是你循环的次数是n,这是你的平方根。
希望这有帮助。
mov eax, 9513135 ; eax = number to take square root of
mov ebx, eax ; make a copy of eax in ebx
loopIt :
sub ebx, count ; count starts as 1, 3, 5, 7, 9
inc count ; count = even
inc count ; count = odd
inc sqrt ; gives sqrt value
mov eax, sqrt
cmp ebx, 0
js timetoReturn ; return value if signed num, aka goes over zero
jnz loopIt
timetoReturn :
mov reg, eax ; just outputting the value
答案 3 :(得分:0)
您可以尝试此算法,它会给出小于或等于数字平方根的整数。
假设您想要n
的平方根。然后不断重复以下计算:
x = (x + n/x) / 2
选择x = n
开始并不断重复,直到x停止变化。
答案 4 :(得分:0)
这是一个简单易懂的算法,用于计算正整数的平方根的底数,用C表示:
int approx_sqrt(int x) {
int result;
for (int partialSum = 0, oddNum = 1; partialSum < x; partialSum += oddNum, oddNum +=2) result++;
return result;
}
它以与okstory的答案相同的原则,以稍微不同的方式。
理论:只要partialSum小于操作数,逐步增加奇数就会被添加到partialSum中。结果等于求和产生partialSum的奇数的数量。
答案 5 :(得分:0)
你们都错了。
您可以使用sqrt.s或sqrt.d汇编代码! 例如)sqrt.s $ f12,$ f13
不要浪费时间来实现这些功能。
答案 6 :(得分:0)
如果您想以 mips 为单位计算整数的平方根,您首先需要将整数转换为浮点数。假设您要取平方根的数字存储在 $t1 中,那么其转换为浮点数将如下所示
mtc1 $t1, $f1
cvt.s.w $f1, $f1
现在您可以使用 sqrt.s 函数计算平方根了。
sqrt.s $f1,$f1
所以现在 $f1 将保存存储在 $t1 中的整数的平方根