不使用比较和条件判断实现min函数,参数为两个32位无符号int。

面试的时候遇到的题目,感觉很有意思。

搜了一下多数现有的解法都是仅有两种限制之一,即要么仅要求不能使用比较,要么仅要求不能使用条件判断,于是打算写一下一种能兼顾两种限制的实现方法。

需要注意的是,条件判断当然也包含三目表达式、switch-case语句甚至abs等隐含条件分支的语法糖或标准库函数,除非能够不借助条件分支实现(例如没有条件分支的abs:参考链接)。

Solution

基本思想很简单,在二进制表示下从高位开始逐位比较,相同的位置可以直接忽略,直到遇到第一个不相同的位置,大小关系就决定了。譬如比较

a=011010
b=010110

时,从高位至低位比较到第三位时两数不同。此时必定是较大者 a 此位为 1,较小者 b 此位为 0,记此位为符号位 sign_a, sign_b

实际上此时我们已经分辨出两数的大小,再想办法将较大者的信息抹掉即可。方法是分别将 a, b 剩余的每一位都与符号位相或,此时较大者 a 后半部分变为全 1,而较小者 b 不变,将两者相与,其结果等于 b,求得min。

在实际实现时可以使用位运算消除条件分支,具体可以参考代码。

"""
myMin(0b011010, 010110) (1)
011010 A
010110 B
^ same 0 vs. 0 (2)
011010 A
010110 B
^ same 1 vs. 1 (3)
011010 A
010110 B
^ diff, sign_A=1, sign_B=0 (4)
011110 A'
010110 B'
^ A_i |= sign_A, B_i |= sign B (5)(6)
011111 A''
010110 B''
^ A_i |= sign_A, B_i |= sign B A'' & B'' = B
""" def myMin(a, b):
found = 0
sign_a, sign_b = 0, 0
for i in range(32, -1, -1):
bit = 1 << i
xa, xb = (a & bit) >> i, (b & bit) >> i # if not found:
# d = xa ^ xb
# else:
# d = 0
d = (not found) & (xa ^ xb) # if xa ^ xb == 1:
# found = 1
found |= xa ^ xb # if d:
# sign_a, sign_b = xa, xb
sign_a |= d & xa
sign_b |= d & xb a |= sign_a * bit
b |= sign_b * bit
return a&b # 用于生成随机测试用例测试正确性
import random, time
loop = 0
MAX = 1<<32
while True:
a, b = random.randint(0, MAX), random.randint(0, MAX)
if myMin(a, b) != min(a, b):
print(f"min({a}, {b}) = {min(a, b)} != {myMin(a, b)}")
break
loop += 1
print(loop, end='\r')
time.sleep(0.001)

不使用比较和条件判断实现min函数的一种方法的更多相关文章

  1. jQuery 判断checkbox是否被选中 4种方法

    下午写JS验证,有一个需求需要判断 checkbox是否被选择,查阅相关资料后,总结以下4种方法,分享给大家. <!DOCTYPE html> <html lang="en ...

  2. C#判断字符串为空的几种方法和效率判断

    C#判断字符串为空的几种方法和效率判断 string定义 1.1 string str1="":会定义指针(栈),并在内存里划一块值为空的存储空间(堆),指针指向这个空间.1.2 ...

  3. 如何通过PHP判断年份是否是闰年----两种方法

    1.定义:闰年是对4取余为0,对100取余不等于0,对400取余等于0的年是闰年. 2.代码: 第一种方法:直接函数判断 $day = date('Y'); if ($day%4==0&&am ...

  4. C# 判断字符串为空的4种方法及效率

    在程序开发过程中,少不了要处理字符串,并且常常要判断字符串是否为空,通常有哪些判断方法,以及不同方法的效率又怎么样? 在 C# 中,通常有三种判断字符串是否为空的方法,下面分别探讨. 1.str.Le ...

  5. js如何判断一个对象是不是Array? 三种方法总有一种可以帮上忙

    转载:http://www.nowamagic.net/librarys/veda/detail/1250 在开发中,我们经常需要判断某个对象是否为数组类型,在Js中检测对象类型的常见方法都有哪些呢? ...

  6. SSE图像算法优化系列十六:经典USM锐化中的分支判断语句SSE实现的几种方法尝试。

    分支判断的语句一般来说是不太适合进行SSE优化的,因为他会破坏代码的并行性,但是也不是所有的都是这样的,在合适的场景中运用SSE还是能对分支预测进行一定的优化的,我们这里以某一个算法的部分代码为例进行 ...

  7. iOS 判断网络连接状态的几种方法

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "PingFang SC"; color: #801b80 } p.p2 ...

  8. PHP中判断变量为空的几种方法

    判断变量为空,在许多场合都会用到,同时自己和许多新手一样也经常会犯一些错误, 所以自己整理了一下PHP中一些常用的.判断变量为空的方法. 1. isset功能:判断变量是否被初始化本函数用来测试变量是 ...

  9. msyql判断记录是否存在的三种方法

    1. select count(*) from .... 这种方法最常见但是效率比较低,因为它需要扫描所有满足条件的记录 2. select 1 from xxxtable where .... 这种 ...

随机推荐

  1. ZAB 和 Paxos 算法的联系与区别?

    相同点: 1.两者都存在一个类似于 Leader 进程的角色,由其负责协调多个 Follower 进程的运行 2.Leader 进程都会等待超过半数的 Follower 做出正确的反馈后,才会将一个提 ...

  2. Mybaits 的优点?

    1.基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任 何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理:提供 XML 标签,支持编写动态 SQL ...

  3. jQuery--文档处理案例

    需求 如上图,实现左右两边的选择菜单可以左右移动,'>'按钮一次只能移动被选中的一个菜单,'>>'按钮一次移动所有被选择的菜单,'>>>'按钮 将所有菜单进行移动, ...

  4. Java 进程和线程

    进程和线程 在并发编程中,有两个基本的执行单元:进程和线程.在Java编程语言中,通常并发编程主要与线程有关.但是进程也很重要. 计算机系统通常具有许多活动的进程和线程.即使在只有一个执行核心,因此在 ...

  5. ModelSerializer序列化器实战

    目录 ModelSerializer序列化器实战 单表操作 序列化器类 视图类 路由 模型 多表操作 models.py serializer.py views.py urls.py ModelSer ...

  6. 理解OIDC协议和认证机制

    当互联网应用越来越多,每个应用程序都实现了自己的身份存储.认证和授权,用户需要在应用上反复的注册与登录,体验糟糕,用户身份信息无法在多个应用间共享与同步.当使用企业应用时,企业提供了一系列应用,尽管是 ...

  7. 谈谈关于CSS中transform属性之scale

    谈谈关于scale属性 scale是什么? 根据W3C定义 ,scale主要是进行缩放和转化: scale能做什么? 1.1px细线 <div class="wrap"> ...

  8. Java/C++实现命令模式---多次撤销和撤回

    某系统需要提供一个命令集合(注:可以使用链表,栈等集合对象实现),用于存储一系列命令对象,并通过该命令集合实现多次undo()和redo()操作,可以使用加法运算来模拟实现.\ 类图: Java代码: ...

  9. 三种获取数据的方法fetch和ajax和axios

    一 .fetch用法 ( 本人比较喜欢fetch,代码精简,虽说目前axios比较流行,但是fetch很多大厂已经开始用fetch开始封装了, 我觉得以后fetch会取代axios和ajax ) 1. ...

  10. properties和XML配置文件内容的获取

    @ 目录 总结内容 1. Java中为什么要使用配置文件 2. Java中常用的配置文件类型有哪些以及它们的特点 Properties配置文件 XML配置文件 总结 总结内容 1. Java中为什么要 ...