为什么Go语言中的浮点数舍入不准确?

huangapple go评论76阅读模式
英文:

Why is Floating Point Numbers rounding Inaccurate in go

问题

我正在使用%0.1f将我的浮点数保留到小数点后一位。然而,我在四舍五入时得到了不同的结果。

package main

import "fmt"

func format() {
    name := "Granth"
    age := 28
    fmt.Print("我的名字是", name, ",我的年龄是", age, "\n")
    fmt.Printf("我的名字是%v,我的年龄是%v\n", name, age)
    fmt.Printf("我的名字是%q,我的年龄是%v\n", name, age)
    fmt.Printf("我的名字是%q,我的年龄是%q\n", name, age)
    fmt.Printf("名字的类型是%T,年龄的类型是%T\n", name, age)
    fmt.Printf("浮点数为%f\n", 34.55)
    fmt.Printf("四舍五入后的浮点数为%0.1f\n", 35.55)
    fmt.Printf("四舍五入后的浮点数为%0.1f\n", 25.55)
}

输出结果为:

我的名字是Granth,我的年龄是28
我的名字是Granth,我的年龄是28
我的名字是"Granth",我的年龄是28
我的名字是"Granth",我的年龄是'\x1c'
名字的类型是string,年龄的类型是int
浮点数为34.550000
四舍五入后的浮点数为35.5
四舍五入后的浮点数为25.6

为什么35.55四舍五入为35.5,而25.55四舍五入为25.6?

Go版本为go1.19.1 windows/amd64。

英文:

I am using %0.1f to round my float to 1 decimal places.
However I am getting different results on rounding.

package main

import "fmt"

func format() {
	name := "Granth"
	age := 28
	fmt.Print("my name is ", name, " and my age is ", age, "\n")
	fmt.Printf("my name is %v and my age is %v\n", name, age)
	fmt.Printf("my name is %q and my age is %v\n", name, age)
	fmt.Printf("my name is %q and my age is %q\n", name, age)
	fmt.Printf("name type is %T and age type is %T\n", name, age)
	fmt.Printf("the float is %f\n", 34.55)
	fmt.Printf("the float rounded off is %0.1f\n", 35.55)
	fmt.Printf("the float rounded off is %0.1f\n", 25.55)
}

and the output is:-

my name is Granth and my age is 28
my name is Granth and my age is 28
my name is "Granth" and my age is 28
my name is "Granth" and my age is '\x1c'
name type is string and age type is int
the float is 34.550000
the float rounded off is 35.5
the float rounded off is 25.6

why is it showing 35.55 rounded as 35.5 and 25.55 rounded as 25.6?

go version go1.19.1 windows/amd64

答案1

得分: 1

你的演示文稿中没有提供所有的有效数字,而且在机器级别上使用的二进制浮点数无法精确表示少数十进制实数值。

例如,如果35.55实际上以接近35.55000000000001的二进制浮点数形式存储,当以一位小数的形式呈现时,它将变为35.6;而如果25.55更精确地表示为25.5499999999999,当以一位小数的形式呈现时,它将四舍五入为25.5,而25.55则保留两位小数。

为了证明这一点,可以将25.55显示到更多的小数位数。我不熟悉Go语言及其对实数表示的处理方式,但IEEE-754双精度二进制浮点数可以将十进制实数精确表示到约15个有效数字。因此,在15个有效数字之后,任何不精确性都将变得明显。

英文:

None of your presentations provide all significant digits, and few decimal real values can be precisely represented in binary floating point used at the machine-level.

So if for example 35.55 were actually stored in binary floating point as something closer to say 35.55000000000001, it will become 35.6 when presented to one decimal place, whereas if 25.55 were more precisely 25.5499999999999, it would round to 25.5 when presented to one decimal place, and 25.55 to two.

To demonstrate this, display 25.55 to more decimal places. I am not familiar with go and it's handling if real number representation, but IEEE-754 double precision binary floating point can represent decimal real numbers to a precision of about 15 significant figures. So any imprecision will be evident after 15 significant figures.

huangapple
  • 本文由 发表于 2022年9月24日 16:35:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/73835818.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定