ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > E文精选 > 函数与公式 > 【公式解析系列】之LOOKUP(2,1/(条件),查找数组或区域)

【公式解析系列】之LOOKUP(2,1/(条件),查找数组或区域)

作者:绿色风 分类: 时间:2022-08-17 浏览:131
楼主
gouweicao78
LOOKUP函数有一个经典的条件查找解法,通用公式基本可以写为:

  1. LOOKUP(2,1/(条件),查找数组或区域)     

  2. LOOKUP(1,0/(条件),查找数组或区域)
很多初学者对此感觉非常诧异就,主要疑惑有:
1、公式中的2、1、0等数字有什么含义,明明在查找条件与这3个数字根本毫无联系,怎么能得到正确结果?
2、明明LOOKUP函数说明需要“升序”查找,否则可能无法返回正确的值,上面这种解法又是如何得改变这一说法呢?
3、据说LOOKUP函数的查找顺序是“二分法”,并且有流程图可循,是否可以结合此例进行讲解?


【函数帮助信息摘录】
语法:LOOKUP(lookup_value, lookup_vector, result_vector)
1、[要点]  lookup_vector 中的值必须以升序排列:...,-2, -1, 0, 1, 2, ..., A-Z, FALSE, TRUE。否则,LOOKUP 可能无法返回正确的值。大写文本和小写文本是等同的。
2、如果 LOOKUP 函数找不到 lookup_value,则它与 lookup_vector 中小于或等于 lookup_value 的最大值匹配。
3、如果 lookup_value 小于 lookup_vector 中的最小值,则 LOOKUP 会返回 #N/A 错误值。


【释疑】简要地说,从逻辑推理来看:
1、首先,条件是一组逻辑判断的值或逻辑运算得到的由TRUE和FALSE组成或者0与非0组成的数组,因而:1/(条件)的作用是用于构建一个由1或者#DIV!0错误组成的值。
2、根据LOOKUP函数说明中的这一条:

也就是说,要在一个由1和#DIV!0组成的数组中查找2,肯定找不到2,因而将返回小于或等于2的最大值(也就是1)匹配

为什么要用2来查找1或用1来查找0呢?因为如果有多个与第1参数相等的值,则Lookup就不一定返回“最后一个”所对应的记录,所以必须养成一个良好习惯,
而不要用:LOOKUP(1,1/(条件),……,或LOOKUP(,0/(条件),……

3、如果有多个满足条件的纪录,为何只返回最后一个,而不是第一个或其他呢?这个解释就需要二分法流程图的模拟了。而对于一般使用者来说,只需要记住“查找满足条件的最后一个记录”可以使用通用公式
  1. LOOKUP(2,1/(条件),查找数组或区域)     

  2. LOOKUP(1,0/(条件),查找数组或区域)
【参考链接】
gouweicao78《Lookup函数二分法模拟器http://www.exceltip.net/thread-285-1-1.html

willin2000修正后的《LOOKUP查找策略完整流程图http://www.exceltip.net/thread-308-1-1.html
2楼
gouweicao78
示例:
用LOOKUP查找2个条件的数据.rar

如图:

 

公式:

  1. =LOOKUP(2,1/((E2=$A$2:$A$9)*(F2=$B$2:$B$9)),C2:C9)
根据Willin2000兄的完整流程图,一步一步判断走向和计算。

一、需要明白的几个含义:
1、posi——表示节点号n,A(posi)表示第n个值,比如posi=2,则表示LOOKUP第2参数数组中的第2个值;
2、X——表示Lookup的第一个参数,即查找的值,也就是上述公式中的“2”;
3、TYPE——表示数据类型,比如:数值、文本、逻辑值、错误值等;
4、left、right——表示二分法取值范围,即左边从数组的第几个值开始取,右边截止到数组的第几个值。初始状态下left=1,right=N表示从第1到第N整个数组所有的值都算。
上例中:1/(条件)得到的数组为:

  1. {#DIV/0!;1;#DIV/0!;#DIV/0!;#DIV/0!;1;#DIV/0!;#DIV/0!}——共8个值
所以,第一次posi=int((1+8)/2)=4——即从该数组的一半处分开(这也是“二分法”的由来)

二、需要注意的问题
上面的posi、left、right都是变量,在流程图中,根据规则不断修正从而得到下一步的posi点,而LOOKUP函数最终也是通过定位最后的posi点来返回查找结果的。


模拟动画如下(请单击动画或下载后观看,以便获得更佳效果):二分法流程图演示.gif
 
3楼
swallow5121
貌似用斑竹提到的两种公式,lookup_vector不需要按升序排列,不知道是不是这样,请斑竹及各位高手指导一下。
4楼
gouweicao78
1、LOOKUP为什么需要lookup_vector升序排列?
从二分法的角度来说,数据以升序排列的方式是最合理的,就像我们翻字典可以根据首字拼音字母直接翻到附近,大大缩小需要查找的范围,从而相比从第1个到最后1个查找的“遍历法”来说,是一个非常高效的算法。
举个例子来说:要查字母C,首先第一次二分法是它属于A~M,然后再属于A~G,接着属于A~D,然后再属于C~D,最后敲定为C。也就是大约为5次的查找。假如,我们把字典反过来了(降序排列了),那么LOOKUP就傻眼了,有兴趣可以按照流程图对照走一下,算算大约几次。

2、LOOKUP为什么不需要lookup_vector升序排列?
因为LOOKUP用的是二分法,它根据每一个posi(流程图中的节点)的数据情况决定下一步的流程,即便不是升序排列,它也是如此查找。

3、所谓“高效”,是指LOOKUP本身这种运算是高效的,但是:
1/(条件)——这个首先是条件判断,比如1/(A1:A100="张三"),首先运算100次比较,得到逻辑值,接着运算100次除法,得到1或#DIV!0,最后才是LOOKUP的二分法。

因而,实际上本帖解析的这个解法,并不是“高效”的解法。

综上所述:升序,是为了更高效地运作二分法;此处的“二分法”并非严格意义的二分法,如果给了它并非升序的数据,它也会按照流程来运算。
5楼
swallow5121
我试了试,如果lookup_vector中没有lookup_value ,但是有小于lookup_value的最大值,用斑竹提供的公式得到的是#N/A 错误。不知道斑竹提供的公式是不是有一定的局限,也就是说lookup_vector中必须有lookup_value的值。
6楼
gouweicao78
得到#N/A错误,在流程图中就给出这样的可能啊,你对照流程的走法去算:
比如共10个数据,那么N=10,left=1,right=10,第一个posi=int((left+right)/2)=5,………………
然后判断第5个数据的数据类型是否与lookup_value相同,数据的大小情况如何,再继续判断下一步流程。
7楼
swallow5121
那如果lookup_vector不是按照升序排列,并且lookup_vecto中没有lookup_value的值,我要查找lookup_value的话该怎么办呢。
8楼
gouweicao78
呵呵,一句话,按照流程走。
=LOOKUP("Z",{"A","E","B"}),就符合你说的那种情况,按照流程走最终找到最后一个记录,因为Z比A、E、B都“大”。
=LOOKUP(1,0/(条件),……)也是如此,因为1比0/(条件)的结果(0和#DIV!0,同类型的只有0)都大。
把1换为2,把0换为1也是一个道理。
9楼
swallow5121
可是这样也不能得到正确的答案啦,就像斑竹举的例子里一样,1比0/(条件)的结果始终为false,导致最终的结果还是#N/A ,而正确的答案不是应该为“E”么。
10楼
gouweicao78
如果找不到,也就是(条件)判断都是FALSE,例如:
=LOOKUP(1,0/("Z"={"A","E","B"}),{"A","E","B"})——找到最后一个Z的记录,当然是找不到,导致最终结果为#N/A!错误。


但=LOOKUP("Z",{"A","E","B"})不一样
left=1、right=3,第一个节点为int((1+3)/2)=2,即字母E与Z相比,比Z小。
下一步判断posi(就是2)是否小于right(3),即是否最后一个记录,不是最后一个记录则left=posi+1=2+1=3,接下来:新的posi=int((3+3)/2)=3,也就是字母B,还是比Z小。
下一步判断posi(就是3)是否小于right(3),因为是最后一个记录,则返回A(posi)就是第3个记录B
走一下流程图就知道了,如图:

 
11楼
linghaodu
一群匪夷所思的牛人
12楼
yncxxmj
讲的非常好。
13楼
herenqing
看不懂!有待学习!
14楼
微风
非常感谢
15楼
wangqilong1980
谢谢分享,收藏学习
16楼
庭院幽幽
天哪,好复杂,还是耐心学吧
17楼
wangg913
好帖子,可说是巅峰之作。
当然,更是合众人之智。
希望有一些有针对的例子以为佐证。
18楼
gouweicao78


佐证之事,既然这个流程图已经推理论证出来,也就是符合任何一个这类的公式,任意抓一个来都是例子,都可以套上去验证。
19楼
wubaiwan
好贴,从未见过
20楼
张啸宁
帖子很好,可惜我能力有限,实在看不懂。
21楼
taotao740425
看不懂,只得多学
22楼
远古石器
23楼
ccf
很细致的解释,好好研读!谢谢!
24楼
snowangle007
好复杂啊!只能先收藏了,然后慢慢消化。
25楼
cmf2011
好复杂呀,楼主,麻烦告诉哪里有详细的举例。谢谢!
26楼
tdjxxdkj
是不是必须弄明白这个二分法,实在是看不懂啊。不过非常感谢楼主的耐心。
27楼
tongxinwu
学习了 但看的还是有些晕 要慢慢消化
28楼
peakchu
先收藏了,等下自己研究
29楼
LoveJinLee
看这个GIF
感觉LOOKUP的查找原理,比原有的“二分法”要复杂一些。。
还要比较type
30楼
gouweicao78
这个论证过程是神马和浮云,

大家只需要记住这个用法和注意点:
第1参数要比第2参数大
条件是数组运算,所以建议即便是2007以上版本也不要用整列的数组运算
31楼
lpzxhjp
草版主,怎么哪儿都有你的身影?
32楼
双飞叶
比较深奥的帖子,看不是太 懂
33楼
jlf2003
很细致的解释,好好研读!谢谢!
34楼
kmbobo
草版主 对excel的使用已经出神入化了!pfpf
35楼
Rongson_Chart
草版,你讲的很好~~我太菜了~~学了个皮毛~~~
36楼
uhilt
真正围观中...-_-
37楼
玉丫头
把这个当图表研究,很快就
38楼
好大一棵树王玉
=LOOKUP(1,0/("Z"={"A","E","B"}),{"A","E","B"},看到这纠结了一下,后来明白了,0/("Z"={"A","E","B"}),结果是DIV/0!,所以返回N/A错误!如果有一个返回0,那么,就会有结果了!
39楼
hustclm
看的头大了
40楼
小风筝
终于弄明白是什么意思了。1/()或者0/()这里的1和0不是数字1和0,是逻辑值true和flase。
41楼
小风筝
整明白了
42楼
小风筝
1/(条件)这个用法真是太灵活了
43楼
飞鱼fish
今天用这个公式解决了问题,但是要真正理解还得把这帖子翻来覆去的读读啊
44楼
buwenhl
学习中
45楼
feisail
加深了理解。
46楼
sunny_8848
多谢,学习了
47楼
fish-2013
解析得非常详细,有点明白1/(条件)这个公式了
48楼
yeminqiang





免责声明

有感于原ExcelTip.Net留存知识的价值及部分知识具有的时间限定性因素, 经与ExcelTip.Net站长Apolloh商议并征得其同意, 现将原属ExcelTip.Net的知识帖采集资料于本站点进行展示, 供有需要的人士查询使用,也慰缅曾经的论坛时代。 所示各个帖子的原作者如对版权有异议, 可与本人沟通提出,或于本站点留言,我们会尽快处理。 在此,感谢ExcelTip.Net站长Apolloh的支持,感谢本站点所有人**绿色风(QQ:79664738)**的支持与奉献,特此鸣谢!
------本人网名**KevinChengCW(QQ:1210618015)**原ExcelTip.Net总版主之一

评论列表
sitemap