Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何将float64数字截断为特定精度?_Go_Floating Point_Truncate - Fatal编程技术网

Go 如何将float64数字截断为特定精度?

Go 如何将float64数字截断为特定精度?,go,floating-point,truncate,Go,Floating Point,Truncate,我想将1.234567截断为一个3位数的浮点数,但结果不是我想要的 例如:1.234567=>1.234 package main import ( "strconv" "fmt" ) func main() { f := 1.234567 fmt.Println(strconv.FormatFloat(f, 'f', 3, 64)) //1.235 fmt.Printf("%.3f", f) //1.235 } 有谁能告诉我如何在围棋中执行此操作吗

我想将
1.234567
截断为一个3位数的浮点数,但结果不是我想要的

例如:
1.234567
=>
1.234

package main

import (
    "strconv"
    "fmt"
)

func main() {
    f := 1.234567
    fmt.Println(strconv.FormatFloat(f, 'f', 3, 64)) //1.235
    fmt.Printf("%.3f", f) //1.235
}

有谁能告诉我如何在围棋中执行此操作吗?

您需要手动截断小数,可以是在字符串级别,也可以是使用
math.Floor
之类的工具。

简单的方法(不总是正确的) 对于截断,我们可以利用它丢弃分数位数。这不完全是我们想要的,我们想要保留一些小数位数。因此,为了实现我们想要的,我们可以先将输入乘以10的幂,将想要的分数位数移到“整数”部分,然后在截断后(调用
math.Trunc()
,它将丢弃剩余的分数位数),我们可以除以我们在开始时乘以的10的幂:

f2 := math.Trunc(f*1000) / 1000
将其包装到函数中:

func truncateNaive(f float64, unit float64) float64 {
    return math.Trunc(f/unit) * unit
}
测试它:

f := 1.234567
f2 := truncateNaive(f, 0.001)
fmt.Printf("%.10f\n", f2)
f := 1.234567
f2 := truncate(f, 0.001)
fmt.Printf("%.10f\n", f2)

f = 0.299999999999999988897769753748434595763683319091796875
f2 = truncate(f, 0.001)
fmt.Printf("%.10f\n", f2)
输出:

1.2340000000
0.3000000000
到目前为止还不错,但请注意,我们在
truncateNaive()
中执行算术运算,这可能会导致不必要的舍入,从而改变函数的输出

例如,如果输入是
0.299999999999999888977697537484345957683319091796875
(可通过
float64
值精确表示,请参见),则输出应该是
0.299900000
,但它将是其他内容:

f = 0.299999999999999988897769753748434595763683319091796875
f2 = truncateNaive(f, 0.001)
fmt.Printf("%.10f\n", f2)
输出:

1.2340000000
0.3000000000
试穿这些衣服

在大多数情况下,这种错误的输出可能是不可接受的(除非您从输入非常接近
0.3
–差异小于10-16–输出为
0.3
…)

使用
big.Float
要正确截断所有有效的
float64
值,中间操作必须精确。要实现这一点,使用单个
float64
是不够的。有一些方法可以将输入拆分为2个
float64
值,并对其执行操作(因此精度不会丢失),这将更有效,或者我们可以使用一种更方便的方法,可以是任意精度

下面是上面使用
big.Float
truncateNaive()函数的“转录本”:

func truncate(f float64, unit float64) float64 {
    bf := big.NewFloat(0).SetPrec(1000).SetFloat64(f)
    bu := big.NewFloat(0).SetPrec(1000).SetFloat64(unit)

    bf.Quo(bf, bu)

    // Truncate:
    i := big.NewInt(0)
    bf.Int(i)
    bf.SetInt(i)

    f, _ = bf.Mul(bf, bu).Float64()
    return f
}
测试它:

f := 1.234567
f2 := truncateNaive(f, 0.001)
fmt.Printf("%.10f\n", f2)
f := 1.234567
f2 := truncate(f, 0.001)
fmt.Printf("%.10f\n", f2)

f = 0.299999999999999988897769753748434595763683319091796875
f2 = truncate(f, 0.001)
fmt.Printf("%.10f\n", f2)
输出现在有效(请在以下服务器上尝试):


你想要的是四舍五入(或截断)到3个小数位数,而不是位。对于一般舍入,请参阅可能的重复:我不想要舍入,只需截断为3个小数位数。1.234567=>1.234而不是1.235如果输入是
0.29999999999988897769753748434595763683319091796875
,则会给出错误的结果,请参见我的答案。该数字与float64不符。;-)但是你是对的,当你打了很多个9时,有一个很小的机会出现舍入错误。这个数字可以用一个
float64
来表示。确切地说,请参见
float64
限制为15位小数。由于下面的算法,您有趣的示例呈现为精确的小数序列。尝试将数字@icza更改为:.;-)
float64
类型是二进制表示(),它有有限位来表示数字,但有限二进制数可能有更多的十进制数字。就像有限的
0.3
十进制数有一个无限的二进制表示。(链接的wikipedia页面有这样的例子,请查看。)
f=1.234 f2:=truncate(f,0.001)fmt.Printf(“%.10f\n”,f2)//1.2330000000
@ikool这是因为
1.234
不能用
float64
精确表示。当您将
1.234
分配给
float64
时,将是
1.23399999999999985789145284798
,请参见上的。因此,基本上是截断
1.23399999999999985789145284798
,正确的输出是
1.233