Golang中为什么3*(1/3)不等于3*1/3
Golang中为什么3*(1/3)不等于3*1/3 大家好,请允许我简单介绍一下自己,我是柏林一所文理中学的老师,正在为我的信息学课程准备一些Go语言的练习。我的主要教学科目是音乐和德语。这是我在这里的第一次发帖。
以下代码:
VAR result float64
result=3*(1/3)
fmt.Printf("Result is %.2f", result)
输出结果为 0
当我将计算式改为 3*1/3(去掉圆括号)时,它正确地输出了 1。
有人能向我解释一下这种行为吗?这与Go编译器的工作方式有关,还是数据类型的问题?
此致!
简而言之:
3*(1/3) 仅由整数组成,因此计算也将使用整数进行。考虑到这一点,1/3 等于 0,这使得结果为零。
你可以使用 3*(1.0/3),这样就没问题了。
func main() {
fmt.Println("hello world")
}
更多关于Golang中为什么3*(1/3)不等于3*1/3的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
基本上,问题在于:
- 在Go(以及我所知道的所有其他类C语言)中,数字具有类型。
- Go(以及我所知道的所有其他类C语言)会对每个表达式进行求值。
Go中的数字类型:
在Go中,数字可以是整数、浮点数或复数。构成你的 3*(1/3) 表达式的 3、1 和 3 都是整数,因此适用整数运算规则:
当你写下 3*(1/3) 时,Go理解运算符优先级,知道必须先计算 1/3。当处理整数时,1 / 3 = 0,余数为1。Go不保留余数,所以你只剩下0。3 * 0 = 0。
当你去掉括号时,因为除法和乘法具有相同的优先级和结合性,Go会先计算 3 * 1 = 3,然后计算 3 / 3 = 1,余数为0,所以结果是1。
表达式求值
当我们看到像 1/3 这样的表达式时,我们通常有一种直觉,觉得可能应该把这个数字保留为分数形式。大多数用Go编程的人生活在以十进制为常态的社会中。我们知道1/3不能很好地转换为十进制。如果你将每个表达式四舍五入到十分位,那么 1 / 3 = 0.3,然后 0.3 * 3 得到 0.9,而不是 1.0。当我们在脑海中计算表达式 3 * (1/3) 时,我们在概念上把 1/3 保留为分数,而不是计算它,然后乘以 3 得到 3/3 = 1。Go(以及我所知道的所有其他类C语言)并不“知道”这一点,因此那些不能很好地适应计算机二进制系统的表达式仍然会被求值。
一种解决方法是使用 math/big 包。该包定义了一个 big.Rat 类型(意为“大有理数”),可以表示像 1/3 这样的比例。与直接写出运算符相比,它的API有些笨拙,但它的设计旨在处理任意精度有理数时既准确又快速。
编辑:有人提出了一个很好的观点,如果你将 1/3 中的 1 或 3 改为 1.0 或 3.0,那么 1/3 的求值将变成 float64 类型,你又会得到正确的答案。


