【问题标题】:How to count decimal places of float?如何计算浮点数的小数位?
【发布时间】:2021-03-31 01:21:22
【问题描述】:

我想检查 float32 是否有两位小数。我的 javascript 方法如下:

step  := 0.01
value := 9.99

if int(value/step) % 1 == 0 {
    printf("has two decimal places!")
}

上面的例子也有效。但是,当 step 不正确时,它将无法正常工作,然后无法正确从 float64 转换为 int。

例子:

step  := 0.1
value := 9.99

if int(value/step) % 1 == 0 {
    printf("has two decimal places!")
}

编译器错误:constant 9.99 truncated to integer

当我们使用动态值时,它只会为每种情况返回 true。

那么计算小数位数的正确方法是什么?

【问题讨论】:

    标签: casting go floating-point-precision


    【解决方案1】:

    你必须欺骗它,添加一个额外的变量:

    step := 0.1
    value := 9.99
    steps := value / step
    if int(steps)%1 == 0 {
        fmt.Println("has two decimal places!")
    }
    

    或在将其转换为 int 之前先转换步骤:

    int(float64(value / step))
    

    playground

    //编辑

    hacky 的非数学方式是将其转换为字符串并拆分,例如:

    func NumDecPlaces(v float64) int {
        s := strconv.FormatFloat(v, 'f', -1, 64)
        i := strings.IndexByte(s, '.')
        if i > -1 {
            return len(s) - i - 1
        }
        return 0
    }
    

    playground

    //更新了一些小优化

    【讨论】:

    • 检查更新,添加了一个“hacky”版本,更相当于你在 python / javascript 中的操作方式。
    • 如果我在您的第一个游乐场将 9.99 更改为 9.9,它仍然显示为 2DP
    【解决方案2】:

    这是一个获取浮点数小数部分的函数。可以使用len(decimalPortion(n))获取小数位数。

    func decimalPortion(n float64) string {
        decimalPlaces := fmt.Sprintf("%f", n-math.Floor(n)) // produces 0.xxxx0000
        decimalPlaces = strings.Replace(decimalPlaces, "0.", "", -1) // remove 0.
        decimalPlaces = strings.TrimRight(decimalPlaces, "0") // remove trailing 0s
        return decimalPlaces
    }
    

    查看playground

    【讨论】:

      【解决方案3】:

      int value %1 永远为零!

      我建议另一种方式:

      value := float32(9.99)
      valuef := value*100
      extra := valuef - float32(int(valuef))
      if extra < 1e-5 {
          fmt.Println("has two decimal places!");
      }
      

      http://play.golang.org/p/LQQ8T6SIY2

      更新

      package main
      
      import (
          "math"
      )
      
      func main() {
          value := float32(9.9990001)
      
          println(checkDecimalPlaces(3, value))
      }
      
      func checkDecimalPlaces(i int, value float32) bool {
          valuef := value * float32(math.Pow(10.0, float64(i)))
          println(valuef)
          extra := valuef - float32(int(valuef))
      
          return extra == 0
      }
      

      http://play.golang.org/p/jXRhHsCYL-

      【讨论】:

      • 是否有可能使这更加动态?这看起来如何具有动态步骤的功能?使用您的示例,我需要对 1001e-5 进行硬编码。
      • @bodokaiser 查看更新,但当值非常接近 9.99 时会失败,例如 9.990000001
      • 谢谢。不要介意我让这个问题有点开放。否则我稍后会标记它:)
      • checkDecimalPlaces(3, value) 例如,如果值为 9.12,则为 true。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多