浅谈上溢overflow和下溢underflow

2025-05-14 08:16:10

目录

一、为什么会出现overflow和underflow?二、解决方法

一、为什么会出现overflow和underflow?

计算机只能使用有限的bit来描述数字,因此当被描述的数字需要超多的bit位,而计算机的bit位不够时,计算机就不能准确地表示这些数字。

例如,因为计算机没有足够的bit位,所以不能描述一个极小的数

1

×

1

0

10000

1×10^{-10000}

1×10−10000 ,计算机会认为这个数是0 。这种误把一个极小的数看作 0 的现象叫做underflow。 计算机也不能描述一个极大的数

1

×

1

0

10000

1×10^{10000}

1×1010000 ,计算机会认为这不是一个数字。这种误把一个级大的数看作

+

+\infty

+∞的现象叫做overflow。

上述现象被称为Rounding,Rounding有时候会产生严重的计算错误。

例如:

1

1

×

1

0

10000

\frac{1}{1×10^{-10000}}

1×10−100001​是有意义的,且其值应该为

1

0

10000

10^{10000}

1010000 。但是由于bit位不够,计算机会把分母当成0来处理,由于分母不能为0,就会出现严重的计算错误。

由overflow和underflow现象产生的错误叫做Rounding Error。

Rounding Error有时会导致系统奔溃,所以我们必须采用一些方式来避免这种问题。

二、解决方法

解决问题的思路就是要通过变形,将极大数极小数变形为普通数,下面用softmax函数的例子来说明这个解决办法。

softmax函数是一个归一化函数。他把一个元素取值范围为 R 的数组归一化为 (0,1) ,并且元素的和为1。归一化之后,数组的元素可以看作是概率分布。其函数形式如下:

s

o

f

t

m

a

x

(

x

i

)

=

e

x

i

i

=

1

N

e

x

i

softmax(x_i)=\frac{e^{x_i}}{\sum_{i=1}^{N}e^{x_i}}

softmax(xi​)=∑i=1N​exi​exi​​ 其中,N为数组中的元素个数,

x

i

x_i

xi​的取值范围为

(

R

,

R

)

(-R,R)

(−R,R),那么

e

x

i

e^{x_i}

exi​的取值范围为

(

0

,

+

)

(0,+\infty)

(0,+∞); 借用知乎上一副图来说明softmax函数的计算过程(感谢该作者画出这么好的图): 当恰好

e

x

i

e^{x_i}

exi​的值都为极小数时,计算机在计算softmax函数的过程中会把

e

x

i

e^{x_i}

exi​和分母

i

=

1

N

e

x

i

\sum_{i=1}^{N}e^{x_i}

∑i=1N​exi​都认为是0,这时就会出现underflow;同理,当恰好

e

x

i

e^{x_i}

exi​的值都为极大数时,就会出现overflow,导致计算结果出现重大错误。为了解决softmax函数的underflow和overflow问题,我们要通过变形,将极大数极小数变形为普通数,具体地如下: 找出数组中最大的数,令

M

=

m

a

x

(

x

1

,

x

2

,

.

.

.

,

x

N

)

M=max(x_1,x_2,...,x_N)

M=max(x1​,x2​,...,xN​),对softmax函数进行变形:

s

o

f

t

m

a

x

(

z

i

)

=

s

o

f

t

m

a

x

(

x

i

M

)

=

e

x

i

M

i

=

1

N

e

x

i

M

softmax(z_i) = softmax(x_i-M) = \frac{e^{x_i-M}}{\sum_{i=1}^{N}e^{x_i-M}}

softmax(zi​)=softmax(xi​−M)=∑i=1N​exi​−Mexi​−M​ 变换之后,对任意的

x

i

M

x_i\le M

xi​≤M,

e

x

i

M

e^{x_i-M}

exi​−M最小值为0,此时分子的取值范围为

(

0

,

1

)

(0,1)

(0,1),分母的取值范围为

(

1

,

N

)

(1,N)

(1,N),无论如何都不会出现上溢和下溢。但仍然有一个问题:如果softmax函数中的分子发生下溢出时,如果我们把softmax函数的计算结果再拿去计算 log,即 log softmax,其实就相当于计算 log(0),所以会得到

-\infty

−∞,但这实际上是错误的,因为它是由舍入误差造成的计算错误。所以,有没有一个方法,可以把这个问题也解决掉呢?答案还是采用和前面类似的策略来计算 log softmax 函数值(感谢原作者写出这么好的公式): 在最后的表达式中,会产生下溢出的因素已经被消除掉了——求和项中,至少有一项的值为1,这使得log后面的值不会下溢出,也就不会发生计算 log(0) 的情况。

问清楚华为vision智慧屏和v系列区别如何?都说说选择哪个好些?
真相了!为什么iPhone的4G网速越来越慢了?