在工作中,我们可以会遇到这样的问题,两组大量的小数相乘,然后比较两组结果的大小。例如100个0.0001相乘与100个0.0002相乘,哪个结果大?很显然,100个0.0002相乘的结果比较大。但是在计算机中,太多的小数相乘,会遇到下溢问题,即变量小时位数太多,无法完全存储。例如本例中,两组结果小时位数都将达到400位,这时候输出两组结构,都将是0,这时候就无法比较大小了,解决这个问题的方法,是对结果取自然对数。 这里使用到对数的两个特性: 第一个是对应f(x)和ln(f(x)),他们在相同的区间内,虽然结果不一样,但是都具有相同的单调性,即同时增加同时减小 第二个是ln(a*b)=ln(a)+ln(b) 第一个特性,我们可以通过下图直观的看到: 对于两个数,对较大的数取自然对数,结果也一定大于对较小的数取自然对数的结果。比如:ln(0.123)>ln(0.122) 回到本例中,如果先计算0.0001^100和0.0002^100,其结果已经下溢为0了,然后再他们取自然对数,那他们的结果肯定是相等的,所以这里就要使用对数的第二个特性:ln(a*b)=ln(a)+ln(b)将先乘再取对数,转换为先求对数,再求和。在本例中就是 m=ln(0.0001^100)=ln(0.001)+ln(0.001)+ln(0.001)…… n=ln(0.0002^100)=ln(0.002)+ln(0.002)+ln(0.002)…… 最后得到的结果必定n>m 以下为python的测试代码:
a=[0.0001]*100 #初始化1个个包含100个0.0001的列表 b=[0.0002]*100 #初始化1个个包含100个0.0002的列表 m=1 n=1 for d in a: #直接计算两个列表中元素的乘积 m*=d for d in b: n*=d print('m=:'+str(m)+',n='+str(n)) #输出结果,可以得知,m,n的结果都是0 print(n>m) for d in a: #转换成自然对数的求和 m+=log(d) for d in b: n+=log(d) print('m=:'+str(m)+',n='+str(n)) #输出m,n的值 print(n>m) #比较m,n得到正确的结果 输出结果: runfile('C:/Users/Administrator/untitled5.py', wdir='C:/Users/Administrator') m=:0.0,n=0.0 False m=:-921.034037198,n=-851.719319142 True