为什么转换后的float64变量的值为1.590000033378601
?
1.59
看起来很小,可以装入32位:
package main
import (
"fmt"
"strconv"
)
func main() {
str := `1.59`
float, err := strconv.ParseFloat(str, 32)
if err != nil {
fmt.Println("err: ", err)
}
fmt.Printf("%T -> %+v\n", float, float)
}
答案 0 :(得分:4)
是32位变量的精度问题。这不是Go的问题。请参阅以下网址。
Single-precision floating-point format - Wikipedia
您将了解此C代码中1.59会发生什么。
#include <stdio.h>
int
main(int argc, char* argv[]) {
float f = 1.59;
if (f == 1.59) {
puts("float: equal!");
} else {
puts("float: not equal!");
}
double d = 1.59;
if (d == 1.59) {
puts("double: equal!");
} else {
puts("double: not equal!");
}
return 0;
}
1.590000033378601在32位变量中为1.59。因此,您可以将值与cast一起使用到float32。即float32(1.590000033378601)
package main
import (
"fmt"
"strconv"
)
func main() {
str := `1.59`
f64, err := strconv.ParseFloat(str, 32)
if err != nil {
fmt.Println("err: ", err)
}
f32 := float32(f64)
fmt.Printf("%T -> %+v\n", f32, f32)
}
在大多数计算机上,浮点值存储为以下元素。
例如,表示0.75是+1.1 x 2^-1
+
为Sign,.1
为有效,-1
为Exponent。这在32位存储空间中存储如下。
Sign Significand
+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+
Exponent
例如,0.75
存储如下
0-01111110-10000000000000000000000
+- Significand
|
+ 1[.1] x 2 ^ -1
| | |
+- Sign | +- Exponent
|
+------ Base
+ 1.1 x 2 ^ -1 = 1 x 2 ^ 0 + 1 x 2 ^ -1 x 2 ^ -1 = 0.75
由于浮点值如上所示,因此数学值与计算机的值不同。这是精确问题。
答案 1 :(得分:1)
十进制数1.59
看起来很短,但这只是因为我们使用十进制数字系统。
当计算机试图用二进制科学记数法(a * 2^b
)表示相同的数字时,它需要更多的小数位数:1.1001011100001010001111010111000010100011110101110001 * 2^0
。
如果将此值四舍五入为32位,则将其存储在float32
类型的变量中,然后以十进制格式打印,得到1.59
,但在float64
中存储相同的舍入值变量和打印为十进制,得到1.590000033378601
。
函数strconv.ParseFloat
返回float64,但由于您指定了32位精度,因此您应该在使用之前将值转换为float32。