您需要了解一些内容:100.55是十进制数(以十进制基数表示)。100.55十进制是一个有限数,正是这样:100.55。


计算机通常以二进制表示形式存储数字。该数100.55不能用有限二进制数表示:100.55是二进制表示中的无限数(与1/3不能用有限十进制数表示的原因相同,它是一个无限序列:)0.333333333....。


但是 Go(像任何其他语言一样)float64使用IEEE-754标准存储类型,这是一种有限的二进制表示。一个float64值在内存中使用64位来描述数字,其中53位用于描述数字,11位用于指数。


现在当你“说”这个:


x := 100.55

这是一个简短的变量声明,它将创建一个名为的新变量,x并从右侧表达式推断其类型,该表达式是一个浮点文字,因此 Go 规范x的类型将为float64. 必须“转换”浮点文字才能使用 64 位表示(由 指定的规则IEEE-754)。并且由于100.55需要以二进制基数精确表示无限位,因此仅使用 64 位(数字为 53),结果将不会(不能)完全正确100.55(但 IEEE-754 格式的 64 位二进制数是最接近的)到它),即:


x := 100.55

fmt.Printf("%.50f\n", x)


100.54999999999999715782905695959925651550292968750000

所以你已经开始了一个数字 not be 100.55。


你100从中减去(float64(int(x))正好是100.0):


x = x - float64(int(x))

fmt.Printf("%.50f\n", x)


0.54999999999999715782905695959925651550292968750000

你能为这个做什么?真的没什么。您期望的结果 ( 0.55) 也是二进制表示中的无限数,因此您无法0.55在类型为 的变量中获得确切的数字float64。


您可以做的是照常使用该数字,但在打印时,请将其四舍五入到您选择的小数位。最简单的方法是使用fmt.Printf(), 并使用%f包含精度的动词指定格式字符串:


fmt.Printf("%.2f\n", x)

结果:


0.55

另一种选择是避免使用浮点数。例如,如果您要表示美元金额,您可以“乘以”您的所有值,100并将金额表示为美分 (1$*100),这是一个整数。只有当您需要将结果打印为美元时,您才可以打印类似


cents := 10055

fmt.Printf("%d.%d $", cents/100, cents%100)

输出:


100.55 $