提问人:despinxz 提问时间:10/11/2023 最后编辑:ggorlendespinxz 更新时间:10/11/2023 访问量:18
MIPS:在处理双精度时如何保持精度,或者将它们四舍五入到特定的小数位数?
MIPS: How to maintain precision when working with doubles or to round them to a specific number of decimal places?
问:
我正在MIPS汇编(使用MARS)中编写一个程序,该程序从.txt文件中读取数字并将其加载到向量中。其中一些数字是双倍的。该程序及其逻辑通常有效,但我遇到了一些未正确计算的数字的问题。例如,.txt 文件中的数字 0.672 存储为 0.6719999999999999。该故障偶尔会在附加项中发生。有哪些方法可以解决这个问题?
如果你好奇,这是我的代码(评论是葡萄牙语):
.data
fim: .double -1.0
zero: .double 0.0
dez: .double 10.0
filename: .asciiz "xtrain.txt"
quebra_linha: .asciiz "\n"
espaco: .asciiz " "
buffer: .space 17408
.align 3
vetor: .space 4000
.text
ler_arq: # lê o arquivo
la $a0, filename
li $a1, 0
li $a2, 0
li $v0, 13
syscall
load: # carrega arquivo no buffer
move $a0, $v0
la $a1, buffer
li $a2, 17408
li $v0, 14
syscall
ler_nums: # lê byte por byte do arquivo
la $s0, vetor
move $s1, $s0
la $t0, buffer
l.d $f10, dez
copy_num:
lb $t1, 0($t0) # carrega caracter atual em t1
bne $t1, '.', cont # se o caracter não for um ponto, pula as próximas linhas
li $t3, 1 # se for um ponto, t3 é setado para 1 (como se fosse True)
addiu $t0, $t0, 1
lb $t1, 0($t0) # avança para o próximo byte
cont:
beq $t1, ',', num_end
beq $t1, '\r', num_end
beq $t1, '\n', fim_copia # se o caracter for uma vírgula ou quebra de linha, termina de copiar o número atual
beq $t1, 0, end # se o arquivo terminar, vai para o fim do código
subu $t1, $t1, 48 # transforma ascii em int
beq $t3, 1, le_double # se t3 for True, pula para le_double
le_int:
mul $t2, $t2, 10 # multiplica o int armazenado anteriormente por 10
add $t2, $t2, $t1 # adiciona o caracter atual
j fim_copia
le_double:
mtc1 $t1, $f0
cvt.d.w $f0, $f0 # converte para double
addiu $t4, $t4, 1 # contador de 10
# loop para dividir o número por 10^t4
loop_double:
div.d $f0, $f0, $f10
addiu $t5, $t5, 1
blt $t5, $t4, loop_double
add.d $f2, $f2, $f0
li $t5, 0
j fim_copia
num_end:
mtc1 $t2, $f4
cvt.d.w $f4, $f4 # converte para double
add.d $f4, $f4, $f2
s.d $f4, 0($s1)
li $t2, 0 # reinicia acumulador inteiro
li $t3, 0 # seta t3 pra False
li $t4, 0 # reinicia contador 10
l.d, $f0, zero # reinicia f0
l.d, $f2, zero
addiu $s1, $s1, 8 # avança posição no vetor
j fim_copia
fim_copia:
addiu $t0, $t0, 1
j copy_num
end:
mtc1 $t2, $f0
cvt.d.w $f0, $f0
s.d $f0, 0($s1) # carrega o último número no vetor
addiu $s1, $s1, 8
l.d $f0, fim # carrega -1.0 no fim do vetor
s.d $f0, 0($s1)
l.d $f12, 0($s0) # passa o início do vetor para f12 como parâmetro
# loop para printar cada linha e número do programa
loop:
addiu $t9, $t9, 1
li $v0, 3
syscall
la $a0, espaco
li $v0, 4
syscall
addi $s0, $s0, 8
l.d $f12, 0($s0)
bne $t9, 8, cont_fq
la $a0, quebra_linha
li $v0, 4
syscall
li $t9, 0
cont_fq:
c.eq.d $f12, $f0
bc1f loop
我试过从双精度更改为单精度,老实说,我不确定还能尝试什么。
答: 暂无答案
评论
printf