zoukankan      html  css  js  c++  java
  • 小梦 在 民科吧 发了一个 用 四则运算 开平方 的 帖

    小梦  在 民科吧 发了一个 帖   《民科编程大赛:用四则运算开平方》  https://tieba.baidu.com/p/6809881927    ,

     

    标题 还是 红颜色 的   ……     哦  ……

     

    早在 古代,   我们的 先人 根据 杨辉三角,  就已经 发明了  开任意次方 的 方法  。      So   ?

     

    ylyyjjlh2     ,   你们 的  插值法 、插花法 、二分法 、二叉树法 、树叶法,      效率 比不上 先人 的 方法 吧 ? 

    你在   《民科编程大赛:用四则运算开平方》  https://tieba.baidu.com/p/6809881927     的  19 楼  说  :   “小数后15位,这已经到极限了。”  ,

     

     

     

     

     

    如果 用 先人 的 方法 的 话,    小数点 后 几百位 也是 分分钟 啊  。

     

     

    本吧开心死了 (绮梦璇)    skywalkerwyj (青莲剑歌)     天辩阮幼台 (陈彼方)   

     

     

    本文 已 发到了 反相吧  《小梦 在 民科吧 发了一个 用 四则运算 开平方 的 帖》  https://tieba.baidu.com/p/6811112759    。

     

     

    下面 记录 帖 里 的 一些  回复  。

     

    2 楼

    ylyyjjlh2 :    浮点数精度多少啊?你编程编糊涂了?

    K歌之王 :     浮点双精度 嘛, 差不多 就是 15 位 到 18 位 的 样子, 不过 我们 完全 可以 用一个 数组 编写 一个 无限位数 的 开平方 程序 啊 。

    ylyyjjlh2: 回复 K歌之王 :别尽吹牛,你来啊,不准用库,算它1000位试试。

    K歌之王 :回复 ylyyjjlh2 :可以啊, 库 也是 人 写 的 啊, 我最喜欢 造 轮子 。

    K歌之王 :回复 ylyyjjlh2 :当然, 我不打算 近期 写, 你们也不用等着, 我最近在学习研究 其它 东西 。

     

     

    3 楼

    K歌之王 :

    回复 2 楼      ylyyjjlh2  , 

     

    数据 的 长度 不是 重点,  我想说的是,  如果 不利用  和平方 公式 的 话,  你们 的 那些 什么 插值法 二分法  等等 的 所谓 “数值计算”  “数值分析”  方法  的 性能 都 存在问题 。     

     

    如果要 对  n  开平方,   当 n 的 位数 很多 时 ,   你们 的 时间复杂度  会 很大  。

     

     

    ylyyjjlh2: 能不胡扯吗!

    K歌之王 :回复 ylyyjjlh2 :你从 昨天晚上 到 今天早上 憋了 9 个小时, 就 憋出来 这么 一句话 ?

     

     

    4 楼

    80 年代 的 计算器 已经有了 开平方 的 功能,   那是 用 硬件电路 实现 的 。       只能说,  80 年代 的 水平 真的 高 啊 !

     

    我们现在 用   Power Shell  、Python   玩 这些  ……

     

    我们可以 玩 个 升级版 的,     设计一个 算法,   用 硬件电路 实现 这个 算法,  硬件电路 的 部分 只要 设计 逻辑电路 就可以,   就是说,  画出 逻辑电路 的 设计图   。

     

    小梦,  如何 ?

     

    本吧开心死了 (绮梦璇)    skywalkerwyj (青莲剑歌)     天辩阮幼台 (陈彼方)       ylyyjjlh2   

     

     

    8 楼

    回复 7 楼      ylyyjjlh2 ,

     

    先用 byte 数组 实现一个 无限位数 的 浮点类型, 这个 浮点类型 只要求 有 加 操作, 主要 是 实现 进位 。

     

    不要求 有 其它 操作, 比如 减 、乘 、除 等 。

     

    这样 , 这个 浮点类型 还是 容易 实现 的 。

     

     

    然后, 再用 先人 的 开方法 。

     

     

    ylyyjjlh2: Talk is cheap.Show me the code.

    K歌之王 :回复 ylyyjjlh2 :Talk is great , code is cheap .

     

     

     

    9 楼

    别问是劫是缘 :      其实以前有人用普通计算器的加减乘除就可以手动开平方

     

     

    10 楼

    回复 9 楼   别问是劫是缘    ,

     

    我将 根据 杨辉三角 开任意次方 的 方法 称为  杨辉三角 开方法  。

     

    我想了一下  杨辉三角 开方法 的 步骤,   还是有一点 繁琐 的 。    以 开平方 来说,   在 迭代开方 的 过程中 ,   除了有 余量,  还有一个  累积量  。

     

    这个 累积量  会 增加 一些 步骤,    也就是 会 增加 一些  时间复杂度  。

     

    但不管怎么说,    杨辉三角 开方法 是 一个 正统 的 方法 。   它 的 好处 是 它 是 一个  “级数”  。

     

    虽然 累积量  会 增加 一些 时间复杂度,    但是,  总的来说,   当 开方结果 的 位数 很大 时,    它 的 效率 仍然 优于  一般 的 数值分析 方法  。

     

    累积量 是 一个 级数,   开方结果 也是 一个 级数,   开方结果 级数 里 包含了  累积量 级数  。

     

    在 开高次方 时,   杨辉三角 开方法 的 累积量 有 多个,  比如 开 n 次方,  则 有 n - 1 个 累积量,   从 n - 1 次方 到 1 次方,  每个  次方  有一个 累积量  。

     

    此时,   累积量 的 计算步骤 (公式)   会 膨胀 变得 复杂,   累积量 的 数值 也会 膨胀 急剧 增大,   这会让 程序 变得 复杂,   也会 增加 时间复杂度,   但是,  理论上,   仍然  可以用  杨辉三角 开方法   写出  无限位数  开任意次方  的  程序  。

     

    累积量 也是  余项系数  。

     

     

     

    别问是劫是缘: 我没关注过杨辉三角形开方,但是N-1个累积量,一个数组不就解决了?

     

     

     

    11 楼

    回复 10 楼   别问是劫是缘    ,

     

    比如 开三次方,   a ³  可以写成     

     

    a ³  =   ( a1 + b ) ³

    = a1 ³ + 3 a1 ² b  +  3 a1 b ² + b ³  ,   

     

    a1 已知,    b 未知   。

    这里 产生了 一个 b 的 一次项  3 a1 ² b  ,   一个 b 的 二次项  3 a1 b ²   ,   

    开 n 次方 会 产生 n 个 余项,  最后一个 n 次方 的 余项 的 系数 永远 是 1,   不用管 。  需要 累积 系数 的 余项 是 前面 的 n - 1 个  。

    开三次方 会 产生  3 - 1 =  2   个 需要 累积 系数 的 余项,    这里 是 第一次 迭代,   3 a1 ² b  、3 a1 b ²   就是 第一次 迭代 时 产生 的 这 2 个 余项  。

     

    令  b = b1 + c ,   则,

     

    a1 ³ + 3 a1 ² b  +  3 a1 b ² + b ³   

    =  a1 ³ + 3 a1 ² ( b1 + c )  + 3 a1 ( b1 + c ) ²  +  ( b1 + c ) ³

    =  a1 ³ + 3 a1 ² ( b1 + c )  + 3 a1 ( b1 ² +  2 b1 c + c ² )  +  b1 ³ + 3 b1 ² c + 3 b1 c ² + c ³

    =  a1 ³ + 3 a1 ² b1 + 3 a1 ² c  + 3 a1 b1 ² +  3 a1 * 2 b1 c + 3 a1 c ²   +  b1 ³ + 3 b1 ² c + 3 b1 c ² + c ³

     

    可以看到,

    3 a1 ² ( b1 + c )   中 产生了  c 的 一次项  3 a1 ² c  ,

    3 a1 ( b1 + c ) ²   中 也 产生了 c 的 一次项  3 a1 * 2 b1 c  ,

    ( b1 + c ) ³  中 也 产生了  c 的 一次项  3 b1 ² c  ,

     

    这 3 个  一次项  可以 合并为 一个,  这个项 就是 本次 迭代 产生 的 一次余项  。

     

    同理,

    3 a1 ( b1 + c ) ²   中 也 产生了 c 的 二次项  3 a1 c ²  ,

    ( b1 + c ) ³  中 也 产生了  c 的 二次项  3 b1 c ²  ,

     

    这 2 个 二次项 可以 合并为 一个,   这个项 就是 本次 迭代 产生 的 二次余项   。

     

    接下来 的 开方过程 是  令   c = c1 + d  ,    重复 上述过程  。

     

    所以,   n - 1 个 累积量,  也就是 余项系数,  可以用 一个  长度 为 n - 1 的 数组 保存,   但 每一个 余项系数  都 是 由 上述 的 迭代过程 计算产生,  这个 迭代计算 过程 比较 繁琐,  如果 能将 这个 迭代过程 归纳为 公式,  大概 是 一个 数列 的 通项公式  。

     

    如果 不能 把  余项系数 的 计算过程 归纳 为 通项公式,   那么,  每 迭代一次,  余项系数 的 公式 就会 ”膨胀“  一点,  当然, 这只是一个 形象 的 比喻 。

    另一方面,   从上面的 计算过程 可以看出,   余项系数 是 相乘 一个 倍数 之后 再 相加,  得到 新的 余项系数  。  这可以看作是 成倍增长,  也差不多是 几何级数 。     这是  数值 上 的 ”膨胀“   。

     

    余项系数  膨胀 的 速度 和 开方 的 次方 有关,  次方 越大,    余项系数  膨胀 的 越快  。

     

    另外,    次方 越大,    余项 越多,   一个 余项 需要 合并 的 项  也 越多  。

     

     

     

     

    12 楼

    小梦 在 《民科编程大赛:用四则运算开平方》  https://tieba.baidu.com/p/6809881927     的  20 楼  说  这是 “用泰勒级数进行逼近运算” :

     

     

     

     

    这是 泰勒级数 ?    这不像是 泰勒级数,   这像是 一个 有 二分性质 的 迭代逼近 算法  。

     

    这个 算法 是,   设 b 为 被开方数,   任取一个 正数 a,   令   c  =  ( b - a ² )  /  ( 2 a )  ,   令  a = a + c ,    重复若干次 这个过程,   a 就 很接近 b 的 平方根    了  。

     

    这个 算法 适合 在 计算器 上 使用,  简单,  容易 由  程序 或者 逻辑电路 实现  。

     

    本吧开心死了 (绮梦璇)                  ylyyjjlh2

     

     

     

     

    绮梦璇: 傻子 [ 滑稽 ] 到现在都没看出一阶泰勒展开式? 

    绮梦璇: 回复 K歌之王 :傻子 [ 滑稽 ] 到底看懂了泰勒展开式没

    K歌之王: 回复 绮梦璇 :我看到的是 “小梦级数” 。   [ 滑稽 ] 

     

     

     

     

    13 楼

    ylyyjjlh2 :

    废话那么多,等到花儿都谢了,还没做出来,真的让人着急。下面看看,我对2开方700位,刚好一屏。

     

     

     

     

     

    ylyyjjlh2: 没有金刚钻,就别揽瓷器活。不会做也没人说你是傻瓜,偏要吹牛。

     

     

     

     

     

    14 楼

    回复 12 楼        本吧开心死了 (绮梦璇)

     

    一阶泰勒展开式 ?   就是 泰勒级数 的 第一项 吧 ?         ( b - a ² )  /  ( 2 a )     这个式子 看起来 像 泰勒级数 第一项 ,   但 这只是 “形似”,  实际上 和 本题 没有关系  。

     

    第二,   你 利用    ( b - a ² )  /  ( 2 a )     循环迭代,   这不是 泰勒级数,   可以叫做 “小梦级数”,    你的 滑稽 表情 说明了 这一点  。

     

    第三,   你能 证明 这个 迭代 的 极限 是 根号 b   吗 ?     [ 滑稽 ] 

     

     

     

     

    15 楼

    回复 13 楼   ylyyjjlh2  ,

     

    Congratulations  !     But,   Talk  is  great ,   believe  me     ...

     

    设 a 为 中间结果, 也是 最终结果,    你的 这个算法 避免了 每次迭代 都要 计算    a ²   吗 ?

     

     

     

    ylyyjjlh2: 楼主吵,你除了吹牛还眼瞎,在那个贴子中,1我已经贴出了一堆大数运算的例子,你还在说你们也没有动作,还要啥动作?2我也贴出了代码,你还同我计算问题。真是个憨豆先生?

    K歌之王: 回复 ylyyjjlh2 :吵 is talk, Talk is great , believe me ...

     

     

     

     

    16 楼

    回复 15 楼 @ylyyjjlh2 ,

     

    你们 在 《民科编程大赛:用四则运算开平方》 https://tieba.baidu.com/p/6809881927 里 提出了 不少 算法,

     

    不过 我没细看, 因为 我想 留着 自己研究 。

     

    不过 不看 也知道, 你们 没有 避免 每次 迭代 计算 a ² 。

     

    小梦 的 算法 号称 “泰勒级数”, 明目张胆 的 在 每次 迭代 计算 a ² , 你来 评论看看 。

     

    ylyyjjlh2: 东拉两扯,就是不干正事,我到看看你后面还有什么花样? 

    K歌之王: 回复 ylyyjjlh2 :我的 花样 可多着 呢 。

    我在 12 楼 说了,  小梦 的 算法 简单小巧,   适合 用在 计算器 上,   我们可以 设计一个 硬件电路 来 实现 它  。

    先画 一个 逻辑电路图 :

                        

                                                    

    左边 的   a 、b 、c 、diff 、v1 、v2 、abs_c 、max_diff   是  存储单元,  也就是 内存,   也就是 内存单元,    假设 每个 存储单元 是 64 位 的,   可以 存储  64 位 浮点数  。

    右边 的   F1 、F2 、F3 、F4 、F5 、F6   是  控制单元,   具体 的 控制 和 运算 逻辑 就在 控制单元 里 实现  。

    橙色线 和 橙色箭头 是  控制信号线路 和 信号传递方向,    蓝色线 是 数据线路,     一根 线 在 实际中 可能是 多位 的  。

    绿色线 和 绿色箭头 也是 控制信号线路,    表示 和 橙色 不同 的 控制分支 。

    F1 、F2 、F3 、F4 、F5 、F6    都 会有 数据线 和  相关的 存储单元 相连,    图中 用 蓝线 简略 的 表示,  并没有 画出 具体 的 连接 线路  。

    我们 定义 :      有电压 为 1,  无电压 为 0     。

    开始运算 时,    输入端  输入 一个  1 脉冲,  就可以 触发 电路 开始 进行 开平方 运算  。    注意 是  1 脉冲,   不是 持续 的 1  。

    先介绍一下 存储单元,   

    a   存放 a,    a 是 中间结果,  也是 最终结果

    b   存放 b,    也就是 被开方数

    v1   存放  a ²  

    diff   存放   b  -  a ²   

    v2    存放   2 * a   

    c   存放   diff / v2   

    abs_diff   存放  diff 的 绝对值

    max_diff   存放 精度值,   当    b  -  a ²   的 绝对值 , 也就是  abs_diff   小于  max_diff  时,  a 为 达到 精度 的 开方结果 ,  可以输出  。

    开始 运算 前,     先 把 被开方数  存到  b,    同时 任取一个 正数, 比如 1 ,  存到 a  。

    然后,   向 输入端 输入 一个   1 脉冲,   F1  接收 到  1 脉冲 后 接通电路,  开始工作 。   F1 的 工作 是 发信号 给 运算器,  让 运算器 计算 a ²,  运算器 计算 结束后,   F1 把 计算结果 存放到  v1 ,   同时 发出 一个  1 脉冲,  触发  F2  开始工作  。

    运算器 在  这个 图 里 没有 画出来,    运算器 是 一个 公共部件,     F1 、F2 、F3 、F4 、F5 、F6  都会去调用  。

    F1  的 内部电路  会 在 下文 画出来,   里面 会 画出  F1  调用  运算器 的  电路 和 逻辑  。

    F1  的 内部电路  如下 :

               

                     

    输入端 接收 到  1 脉冲,   这个 1 脉冲 会让  “让 寄存器 A 变成 写入状态”   电路 接通,  这个电路 会 向  寄存器 A  发出 信号,   告诉 寄存器 A 变成 写入状态,

    同时,  输入端  的  1 脉冲  还会 让  “让 寄存器 B 变成 写入状态”  电路 接通,  这个电路 会 向 寄存器 B  发出 信号,   告诉 寄存器 B 变成 写入状态,

    同时,  输入端  的  1 脉冲  会 触发   延时开关,    延时开关 在 一段时间 后 输出 一个  1 脉冲 ,   这个  1 脉冲 会 接通 下一个 操作 的 电路 。

    这样 就可以 在 一个 操作 完成后 触发 下一个 操作 执行  。

    为什么要用 延时开关 呢 ?    是 为了  确保 上一个 操作 完成 后,  才 触发 下一个 操作  。   因为  电路 的 运行 需要时间, 每一段电路 运作 需要 的 时间 也 不完全相同,  所以 需要 延时开关 在 一段时间 后 发出 1 脉冲 触发 下一个 操作,   这段时间 应该 足够 完成 当前操作,   这样 来 确保 触发 下一个 操作时,  当前 操作 已经 完成  。  

    从 图上 可以看到,      “让 寄存器 A 变成 写入状态”    和    “让 寄存器 B 变成 写入状态”   是  F1  的  第一个 步骤,  这 2 个 操作 是 同时执行 的,  也可以说是 并行 执行 的  。

    第 1 个 步骤 有 一个 延时开关,   当   “让 寄存器 A 变成 写入状态”    和    “让 寄存器 B 变成 写入状态”    完成 后,   延时开关 发出 1 脉冲,   触发 下一个 步骤  。

    第 2 个 步骤 包含 2 个 操作,    “打开 a 和 寄存器 A 的 通路,  让 a 的 数据 写入 寄存器 A”  和  “打开 a 和 寄存器 B 的 通路,  让 a 的 数据 写入 寄存器 B”  ,

    这 2 个 操作 也是 同时执行 的,    第 2 个 步骤 也 有 一个  延时开关,   这 2 个 操作 完成 后,     延时开关 发出 1 脉冲,   触发 下一个 步骤  。

    到 目前为止,   每一个 操作 是 一段 电路,   这一段 电路 在 输入端 输入 1 脉冲 时 工作,   1 脉冲 结束 后 电路 停止  。

    1 脉冲  是 有电压,  这个 电压 使得 电路 接通 并 工作,    1 脉冲 结束 后,   无电压,   电路不工作 。  延时开关 被 触发 后,   即使  输入端 的 1 脉冲 结束,  也会 在 设定好 的 时间 后 在 输出端  发出  1 脉冲   。

    当然,  我们需要 知道 每一个 步骤 完成 的 最大时间,  以此 来 设置 这个 步骤 的 延时开关 的 延迟时间,    延迟时间 应该 比 步骤 完成 的 最大时间 更大一点,   这样 有一点 冗余,    有利于 电路 的 稳定运行  。

    延时开关 的 输出端 连接 了 

     

     

     

     

  • 相关阅读:
    jmeter(46) redis
    jmeter(45) tcp/ip协议
    Codeforces Round #538 (Div. 2)D(区间DP,思维)
    Codeforces Global Round 1D(DP,思维)
    Educational Codeforces Round 57D(DP,思维)
    UPC11073(DP,思维)
    Yahoo Progamming Contest 2019D(DP,思维)
    Atcoder Beginner Contest 118D(DP,完全背包,贪心)
    Xuzhou Winter Camp 1C(模拟)
    Educational Codeforces Round 57 (Rated for Div. 2)D(动态规划)
  • 原文地址:https://www.cnblogs.com/KSongKing/p/13296121.html
Copyright © 2011-2022 走看看