MST

星途 面试题库

面试题:Go中高精度处理浮点型舍入误差并优化性能

在一个金融交易系统中,涉及大量高精度浮点数运算,对计算结果的准确性要求极高,同时对性能也有严格要求。现需要处理金额的加减乘除操作,例如计算订单总价、找零等。请基于Go语言设计一个完整的解决方案,既要保证高精度处理浮点型舍入误差,又要在高并发场景下优化性能,详细说明设计思路、关键数据结构及函数实现。
46.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 高精度处理:使用 math/big 包中的 Float 类型来处理高精度浮点数,以避免普通 float32float64 的舍入误差。
  2. 高并发优化
    • 采用缓存机制减少重复计算,例如使用 sync.Map 来缓存一些常用计算结果。
    • 合理使用 goroutinechannel 来实现并发计算,提高整体性能。在并发操作时,对共享资源(如缓存)使用 sync.Mutex 进行保护。

关键数据结构

  1. Money:封装 math/big.Float,方便对金额进行操作。
type Money struct {
    amount *big.Float
}
  1. Cache:用于缓存计算结果。
type Cache struct {
    sync.Map
}

函数实现

  1. 初始化 Money
func NewMoney(value string) (*Money, error) {
    amount, ok := new(big.Float).SetString(value)
    if!ok {
        return nil, fmt.Errorf("invalid money value: %s", value)
    }
    return &Money{amount: amount}, nil
}
  1. 加法操作
func (m *Money) Add(other *Money) *Money {
    result := new(big.Float).Add(m.amount, other.amount)
    return &Money{amount: result}
}
  1. 减法操作
func (m *Money) Sub(other *Money) *Money {
    result := new(big.Float).Sub(m.amount, other.amount)
    return &Money{amount: result}
}
  1. 乘法操作
func (m *Money) Mul(other *Money) *Money {
    result := new(big.Float).Mul(m.amount, other.amount)
    return &Money{amount: result}
}
  1. 除法操作
func (m *Money) Div(other *Money) (*Money, error) {
    if other.amount.Cmp(big.NewFloat(0)) == 0 {
        return nil, fmt.Errorf("division by zero")
    }
    result := new(big.Float).Quo(m.amount, other.amount)
    return &Money{amount: result}, nil
}
  1. 缓存操作
func (c *Cache) Get(key string) (*Money, bool) {
    value, ok := c.Map.Load(key)
    if ok {
        return value.(*Money), true
    }
    return nil, false
}

func (c *Cache) Set(key string, value *Money) {
    c.Map.Store(key, value)
}
  1. 并发计算示例
func concurrentCalculation(m1, m2 *Money, cache *Cache, op string) *Money {
    var result *Money
    key := fmt.Sprintf("%s_%s_%s", m1.amount.String(), m2.amount.String(), op)
    if cached, ok := cache.Get(key); ok {
        return cached
    }

    var ch = make(chan *Money)
    go func() {
        switch op {
        case "add":
            result = m1.Add(m2)
        case "sub":
            result = m1.Sub(m2)
        case "mul":
            result = m1.Mul(m2)
        case "div":
            var err error
            result, err = m1.Div(m2)
            if err != nil {
                close(ch)
                return
            }
        }
        ch <- result
    }()

    if result = <-ch; result != nil {
        cache.Set(key, result)
    }
    return result
}