逐比特校验法-大整数开平方根 Bit-by-Bit Large Number Square Root

本文介绍了如何使用逐比特校验法对大整数进行精确且快速的开平方根操作,这种方法基于二分思想,通过比特级别的验证避免了浮点误差,适合处理密码学中的大数问题。文章详细阐述了算法过程,并提供了Python实现及验证结果。
摘要由CSDN通过智能技术生成

问题描述&背景

描述

给定一个大整数(十进制下可能长达数百位) N N N,并保证其是某个整数的平方,如何精确又快速的求出其平方根?

背景

最近正在学习密码学相关的一些问题,遇到了一个题目,其中需要对几个巨大的整数(密码学日常 -_-)开平方根。遇到巨大的整数,自然想Python大法,毕竟对大整数的支持确实很棒,几乎无限位数的加法与乘法,运算速度也是巨快。没想到在给大整数开平方根这个看似轻巧的问题上卡住了,于是经过一番搜索,找到了一个基于二分思想、非常快速的逐比特验证方法,在这里和大家总结分享一下。

逐比特校验开平方根算法

参考来源

这篇文章比较全面总结了整型开根的各算法,包括精确解与近似的迭代法等:点我查看

二分思想

对大数做平方根时,如果直接做开根,大部分语言都会将其视作浮点型,从而带来误差,无法得到精确解;要想直接对大整型开根也是相当费时的操作。为了精确解,便想到通过循环迭代不断试错,找到精确的那个解,其平方等于 N N N,因为平方操作本质即乘法,是比较快速且准确的。
暴力迭代循环的次数过多,时间上一般不可忍受,于是可采用二分查找,显著减少搜索时间。

更进一步-比特法校验

二分查找仍然需要包含许多平方后比较的操作,运行速度仍然不尽人意。我们可以换一个思路:对于一个整数进行开平方根的操作,本质就是根据一个写为二进制后长 l l l位的整数 N N N构造一个二进制长为 ⌈ l 2 ⌉ \lceil \frac{l}{2} \rceil 2l位的整数 s q r t N sqrtN sqrtN,从高位到低位逐个比特验证每一位是0还是1

bit- k k k k 15 k_{15} k15 k 14 k_{14} k14 k 13 k_{13} k13 k 12 k_{12} k12 k 11 k_{11} k11 k 10 k_{10} k10 k 9 k_9 k9 k 8 k_8 k8 k 7 k_7 k7 k 6 k_6 k6 k 5 k_5 k5 k 4 k_4 k4 k 3 k_3 k3 k 2 k_2 k2 k 1 k_1 k1 k 0 k_0 k0 Dec
N N N 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 1 43681
s q r t N sqrtN sqrtN 1 1 0 1 0 0 0 1 209

引言1:注意到假设 s q r t N sqrtN sqrtN的二进制长为 k k k位,则其最小可能的数的平方为 N = ( 2 k − 1 ) 2 = 2 2 k − 2 N = (2^{k-1})^2 = 2^{2k-2} N=(2k1)2=22k2,长为 2 k − 1 2k-1 2k1位;最大可表示的数的平方为 N = ( 2 k − 1 ) 2 = 2 2 k − 2 k + 1 + 1 N = (2^k - 1)^2 = 2^{2k} - 2^{k+1} + 1 N=(2k1)2=22k2k+1+1,长为 2 k + 1 2k+1 2k+1位。故若输入 N N N的二进制长为 l l l,那么其平方根的二进制长最多为 ⌈ l 2 ⌉ \lceil \frac{l}{2} \rceil 2l位。所以我们只需判断末尾 ⌈ l 2 ⌉ \lceil \frac{l}{2} \rceil 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值