我有这个等式: Summation of sin(x)
我试图通过在MIPS上创建一个程序来计算它。但是,它会输出不正确的大数字!我不知道我犯了什么愚蠢的错误。 我创造了三个函数,一个计算阶乘,另一个计算幂,第三个函数是sin函数。
#read integer
li $v0, 5
syscall
addi $a0, $v0, 0 #argument of sin function, a0 = x
li $t4, 1 #n starting from 1
addi $s7, $v0, 0 #sum = x
jal sin
j end
sin:
Loop:
slti $t5, $t4, 5 #t0 < 5 (n < 5)
beq $t5, 0, exitLoop
addi $sp, $sp, -8 # adjust stack for 2 items
sw $ra, 4($sp) # save return address
sw $a0, 0($sp) # save argument
li $a0, -1 #argument of pow function, number = -1
addi $a1, $t4, 0 #argument of pow function, power = t4
jal power
addi $s0, $v0, 0 #s0 = v0 (return value of pow)
lw $a0, 0($sp) # restore original x
sll $a1, $t4, 1 #a1 = 2n
addi $a1, $a1, 1 #a1 = 2n+1
jal power
addi $s1, $v0, 0 #s0 = v0 (return value of pow)
sll $a0, $t4, 1 #a0 = 2n
addi $a0, $a0, 1 #a0 = 2n + 1
jal factorial
addi $s2, $v0, 0 #s0 = v0 (return value of pow)
lw $a0, 0($sp) # restore original n
lw $ra, 4($sp) # and return address
mult $s0, $s1 # LO = (-1)^n * x^(2n+1)
mflo $s3 # S3 = LO
div $s3, $s2 # s3 / (2n+1!)
mflo $s3
add $s7, $s7, $s3 #sum = sum + s3
addi $t4, $t4, 1 #n++
j Loop
exitLoop:
addi $v1, $s7, 0
addi $sp, $sp, 8
jr $ra
power:
addi $t0 $a0, 0 #t0 = a0
li $t1, 0 #i = 0
loop:
slt $t3, $t1, $a1 #if i < n
beq $t3, 0, exit
mult $t0, $a0 #t0 * a0
mflo $t0 #LO = t0
addi $t1, $t1, 1
j loop
exit:
addi $v0, $t0, 0
jr $ra
factorial:
li $t0, 1
bgt $a0, $t0, L1
li $v0, 1
jr $ra
L1:
addi $sp, $sp, -8 # adjust stack for 2 items
sw $ra, 4($sp) # save return address
sw $a0, 0($sp) # save argument
addi $a0, $a0, -1 # decrement n
jal factorial # recursive call
lw $a0, 0($sp) # restore original n
mul $v0, $a0, $v0 # multiply to get result
lw $ra, 4($sp) # and return address
addi $sp, $sp, 8 # pop 2 items from stack
jr $ra # and return
end:
li $v0, 1
addi $a0, $v1, 0
syscall
答案 0 :(得分:0)
正如Jester所说,你应该使用浮点运算。
通过利用系列中的每个幂项和每个因子项是前一个的简单增量,您还可以大大简化事物。无需从头开始重新计算,也无需递归计算阶乘[它更多 更容易使用循环]。
根本不需要单独的功能。这是C中的函数。这是对asm的一个相对简单的翻译:
double
qsin(double x)
{
double x2;
double cur;
int neg;
double xpow;
double n2m1;
double nfac;
int iters;
double sum;
// square of x
x2 = x * x;
// values for initial terms where n==0:
xpow = x;
n2m1 = 1.0;
nfac = 1.0;
neg = 1;
sum = 0.0;
// NOTES:
// (1) with the setup above, we can just use the loop without any special
// casing
// (2) this _will_ do an unnecessary calculation [that gets thrown away] on
// the last iteration, but it's a tradeoff for simplicity
// (3) when translated to asm, it should be easy to restructure to avoid
// this (i.e. just harder to express in a loop here)
for (iters = 5; iters > 0; --iters) {
// calculate current value
cur = xpow / nfac;
// apply it to sum
if (neg < 0)
sum -= cur;
else
sum += cur;
// now calculate intermediate values for _next_ sum term
// get _next_ power term
xpow *= x2;
// go from factorial(2n+1) to factorial(2n+1+1)
n2m1 += 1.0;
nfac *= n2m1;
// now get factorial(2n+1+1+1)
n2m1 += 1.0;
nfac *= n2m1;
// flip sign
neg = -neg;
}
return sum;
}