MIPS:在处理双精度时如何保持精度,或者将它们四舍五入到特定的小数位数?

MIPS: How to maintain precision when working with doubles or to round them to a specific number of decimal places?

提问人:despinxz 提问时间:10/11/2023 最后编辑:ggorlendespinxz 更新时间:10/11/2023 访问量:18

问:

我正在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
            
 

我试过从双精度更改为单精度,老实说,我不确定还能尝试什么。

MIPS 精密 火星模拟器

评论

0赞 Tangentially Perpendicular 10/11/2023
这回答了你的问题吗?浮点数学坏了吗?
0赞 ggorlen 10/11/2023
你能把它们存储为整数吗?很高兴看到文本文件的简单示例,以及您的预期/实际输出。此外,将您的评论翻译成英语会很有用,因为这是一个全英语网站(如果您想要葡萄牙语,则有 pt.stackoverflow.com)
0赞 Erik Eidt 10/11/2023
浮点有很多问题。一个迫在眉睫的问题是将浮点数转换为字符串(即 或类似)绝对不准确。要消除字符串转换问题,请查看十六进制的浮点变量。printf

答: 暂无答案