为什么 Go 中的浮点数不能溢出而整数可以?
Why can't Go floats overflow but integers can?
我在 Go 中测试了一些东西,注意到整数可以溢出,但 float64
和 float32
显然不能。
f64 := math.MaxFloat64
fmt.Printf("%f\n", f64)
fmt.Printf("%f\n", f64+1)
f32 := math.MaxFloat32
fmt.Printf("%f\n", f32)
fmt.Printf("%f\n", f32+1)
i := math.MaxInt64
fmt.Printf("%d\n", i)
fmt.Printf("%d\n", i+1)
结果:
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
340282346638528859811704183484516925440.000000
340282346638528859811704183484516925440.000000
9223372036854775807
-9223372036854775808
出于性能原因显然没有检查整数溢出,但为什么我不能使浮点数溢出?他们检查了吗?
因为数据结构根本不同。大多数编程语言(包括 Go)用于(至少大部分)浮点数据类型的 two's complement structure used by most programming languages (including Go) for (at least most of) their integral data types overflows as a by-product of how it works; the IEEE-754 floating point 不会溢出,它的工作方式是数字的数量级继续增加,一旦过去在某一点上,即使在整数级别,数字也开始失去精度。
只是将数字数据存储在 fixed-size 位组中的两种机制的工作方式根本不同。
还有其他结构。例如,某些语言具有不固定大小的“大整数”and/or“大小数”类型;相反,它们占用了容纳数字所需的空间。 (Java 的 BigInteger
和 BigDecimal
, JavaScript 的 BigInt
, ...) Go 有 Int
, Rat
,和 math/big
package. (Thanks Adrian!) 中的 Float
fixed-size 非常有用,因为它们非常快;但有时你想要速度以外的东西(扩展范围、更好的浮点精度等),在这种情况下你会牺牲一些速度来换取你需要的其他东西。
我在 Go 中测试了一些东西,注意到整数可以溢出,但 float64
和 float32
显然不能。
f64 := math.MaxFloat64
fmt.Printf("%f\n", f64)
fmt.Printf("%f\n", f64+1)
f32 := math.MaxFloat32
fmt.Printf("%f\n", f32)
fmt.Printf("%f\n", f32+1)
i := math.MaxInt64
fmt.Printf("%d\n", i)
fmt.Printf("%d\n", i+1)
结果:
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
340282346638528859811704183484516925440.000000
340282346638528859811704183484516925440.000000
9223372036854775807
-9223372036854775808
出于性能原因显然没有检查整数溢出,但为什么我不能使浮点数溢出?他们检查了吗?
因为数据结构根本不同。大多数编程语言(包括 Go)用于(至少大部分)浮点数据类型的 two's complement structure used by most programming languages (including Go) for (at least most of) their integral data types overflows as a by-product of how it works; the IEEE-754 floating point 不会溢出,它的工作方式是数字的数量级继续增加,一旦过去在某一点上,即使在整数级别,数字也开始失去精度。
只是将数字数据存储在 fixed-size 位组中的两种机制的工作方式根本不同。
还有其他结构。例如,某些语言具有不固定大小的“大整数”and/or“大小数”类型;相反,它们占用了容纳数字所需的空间。 (Java 的 BigInteger
和 BigDecimal
, JavaScript 的 BigInt
, ...) Go 有 Int
, Rat
,和 math/big
package. (Thanks Adrian!) 中的 Float
fixed-size 非常有用,因为它们非常快;但有时你想要速度以外的东西(扩展范围、更好的浮点精度等),在这种情况下你会牺牲一些速度来换取你需要的其他东西。