分数到小数——模拟

97 阅读1分钟

image.png

代码:

  1. 如果可以整除,余数为 0 ,则直接相除,然后将 int 转 string(strconv.Itoa),然后直接返回就可以了
  2. 如果不能整除,则将整数部分,和小数部分分开计算即可,当然计算前要考虑答案是否为负数,如果为负数,则在 byte 数组中先添加一位 '-'
  3. 整数部分直接整除,然后转字符串,然后将字符串加入 byte 数组即可
  4. 小数部分模拟正常手算,求余数,然后将余数翻十倍再求余数,直到余数为 0 ,或开始出现循环,则退出for循环
  5. 将余数 * 10后,相除,将答案append进答案数组中,然后再保存新的余数
  6. 如何判断是否出现循环,借用map哈希,如果当前余数已经出现,则退出循环,如果没有出现将当前位置计入map,
  7. 退出for是、循环后,要判断是因为余数为0退出的还是因为循环退出的,如果是因为循环,则要将循环第一次出现的位置加上‘(’,最后位置加上')'
  8. 循环退出的位置,即indexMap[remainder]
func fractionToDecimal(numerator, denominator int) string {
    if numerator%denominator == 0 {
        return strconv.Itoa(numerator / denominator)
    }

    s := []byte{}
    if numerator < 0 != (denominator < 0) {
        s = append(s, '-')
    }

    // 整数部分
    numerator = abs(numerator)
    denominator = abs(denominator)
    integerPart := numerator / denominator
    s = append(s, strconv.Itoa(integerPart)...)
    s = append(s, '.')

    // 小数部分
    indexMap := map[int]int{}
    remainder := numerator % denominator
    for remainder != 0 && indexMap[remainder] == 0 {
        indexMap[remainder] = len(s)
        remainder *= 10
        s = append(s, '0'+ byte(remainder/denominator))
        remainder %= denominator
    }
    if remainder > 0 { // 有循环节
        insertIndex := indexMap[remainder]
        s = append(s[:insertIndex], append([]byte{'('}, s[insertIndex:]...)...)
        s = append(s, ')')
    }

    return string(s)
}

func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}