浅谈上溢overflow和下溢underflow

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

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

例如,因为计算机没有足够的bit位,所以不能描述一个极小的数 1 × 1 0 − 10000 1×10^{-10000} 1×1010000 ,计算机会认为这个数是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×10100001是有意义的,且其值应该为 1 0 10000 10^{10000} 1010000 。但是由于bit位不够,计算机会把分母当成0来处理,由于分母不能为0,就会出现严重的计算错误。

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

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

二、解决方法

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

  1. 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=1Nexiexi
    其中,N为数组中的元素个数, x i x_i xi的取值范围为 ( − R , R ) (-R,R) (R,R),那么 e x i e^{x_i} exi的取值范围为 ( 0 , + ∞ ) (0,+\infty) (0,+)
    借用知乎上一副图来说明softmax函数的计算过程(感谢该作者画出这么好的图):
    在这里插入图片描述
  2. 当恰好 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=1Nexi都认为是0,这时就会出现underflow;同理,当恰好 e x i e^{x_i} exi的值都为极大数时,就会出现overflow,导致计算结果出现重大错误。
  3. 为了解决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(xiM)=i=1NexiMexiM
    变换之后,对任意的 x i ≤ M x_i\le M xiM e x i − M e^{x_i-M} exiM最小值为0,此时分子的取值范围为 ( 0 , 1 ) (0,1) (0,1),分母的取值范围为 ( 1 , N ) (1,N) (1,N),无论如何都不会出现上溢和下溢。
  4. 但仍然有一个问题:如果softmax函数中的分子发生下溢出时,如果我们把softmax函数的计算结果再拿去计算 log,即 log softmax,其实就相当于计算 log(0),所以会得到 − ∞ -\infty ,但这实际上是错误的,因为它是由舍入误差造成的计算错误。所以,有没有一个方法,可以把这个问题也解决掉呢?答案还是采用和前面类似的策略来计算 log softmax 函数值(感谢原作者写出这么好的公式):
    在这里插入图片描述
    在最后的表达式中,会产生下溢出的因素已经被消除掉了——求和项中,至少有一项的值为1,这使得log后面的值不会下溢出,也就不会发生计算 log(0) 的情况。
  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
同步FIFO(First-In-First-Out)是一种数据结构,用于在多个处理器或模块之间传输数据。它按照先进先出的原则,将数据从一个模块传输到另一个模块。 上溢下溢是指在同步FIFO中可能出现的两种情况: 1. 上溢Overflow):当发送方向FIFO中写入数据的速度大于接收方向FIFO中读取数据的速度时,发送方向FIFO可能会上溢。这意味着发送方向FIFO已经满了,无法再写入更多的数据。上溢可能导致数据丢失。 2. 下溢(Underflow):当接收方向FIFO中读取数据的速度大于发送方向FIFO中写入数据的速度时,接收方向FIFO可能会下溢。这意味着接收方向FIFO已经空了,无法再读取更多的数据。下溢可能导致数据丢失。 为了避免上溢下溢,设计者可以采取一些策略: 1. 增大FIFO的容量:通过增大FIFO的容量,可以容纳更多的数据,减少上溢的可能性。 2. 控制数据的发送和接收速度:通过合理控制发送和接收数据的速度,避免发送方向FIFO写入速度过快或接收方向FIFO读取速度过快,从而减少上溢下溢的风险。 3. 使用流量控制机制:可以使用流量控制机制,如令牌桶算法或信号量,来动态地控制数据的发送和接收速度,以适应不同模块之间的处理能力差异。 综上所述,上溢下溢是同步FIFO中可能出现的问题,设计者可以通过增大FIFO容量、控制数据速度和使用流量控制机制等手段来避免这些问题的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值