数学魔法结局:muldiv

news2024/12/29 10:51:01

介绍了一些棘手的数学魔法,但我一直没有抽出时间说出妙语。目标是计算

 

同时正确处理溢出。我们的秘密武器是 EVM 的mulmod指令。这条指令完全符合我们的要求,只是它返回的是余数而不是商。那么我们的策略是什么?

  1. 计算 512 位乘积一种⋅b使用mulmod.
  2. 通过使用 减去余数使除法精确mulmod
  3. 从分数中去除二的幂以使分母可逆模组2个256.
  4. 计算分母的模逆。
  5. 乘以分子和反分母模组2个256.

每个步骤的实现我这里就不解释了,具体可以参考之前的帖子:

  • 中国剩余定理
  • 全乘法
  • 512位除法(包括一些简单的技巧)
  • 乘法逆元

实施和优化的策略如下:

contract MulDiv {
    function muldiv(uint256 a, uint256 b, uint256 denominator)
    internal pure returns (uint256 result)
    {
        // Handle division by zero
        require(denominator > 0);

        // 512-bit multiply [prod1 prod0] = a * b
        // Compute the product mod 2**256 and mod 2**256 - 1
        // then use the Chinese Remainder Theorem to reconstruct
        // the 512 bit result. The result is stored in two 256
        // variables such that product = prod1 * 2**256 + prod0
        uint256 prod0; // Least significant 256 bits of the product
        uint256 prod1; // Most significant 256 bits of the product
        assembly {
            let mm := mulmod(a, b, not(0))
            prod0 := mul(a, b)
            prod1 := sub(sub(mm, prod0), lt(mm, prod0))
        }
        
        // Short circuit 256 by 256 division
        // This saves gas when a * b is small, at the cost of making the
        // large case a bit more expensive. Depending on your use case you
        // may want to remove this short circuit and always go through the
        // 512 bit path.
        if (prod1 == 0) {
            assembly {
                result := div(prod0, denominator)
            }
            return result;
        }
        
        ///
        // 512 by 256 division.
        ///
        
        // Handle overflow, the result must be < 2**256
        require(prod1 < denominator);

        // Make division exact by subtracting the remainder from [prod1 prod0]
        // Compute remainder using mulmod
        // Note mulmod(_, _, 0) == 0
        uint256 remainder;
        assembly {
            remainder := mulmod(a, b, denominator)
        }
        // Subtract 256 bit number from 512 bit number
        assembly {
            prod1 := sub(prod1, gt(remainder, prod0))
            prod0 := sub(prod0, remainder)
        }
        
        // Factor powers of two out of denominator
        // Compute largest power of two divisor of denominator.
        // Always >= 1 unless denominator is zero, then twos is zero.
        uint256 twos = -denominator & denominator;
        // Divide denominator by power of two
        assembly {
            denominator := div(denominator, twos)
        }
        
        // Divide [prod1 prod0] by the factors of two
        assembly {
            prod0 := div(prod0, twos)
        }
        // Shift in bits from prod1 into prod0. For this we need
        // to flip `twos` such that it is 2**256 / twos.
        // If twos is zero, then it becomes one
        assembly {
            twos := add(div(sub(0, twos), twos), 1)
        }
        prod0 |= prod1 * twos;
        
        // Invert denominator mod 2**256
        // Now that denominator is an odd number, it has an inverse
        // modulo 2**256 such that denominator * inv = 1 mod 2**256.
        // Compute the inverse by starting with a seed that is correct
        // correct for four bits. That is, denominator * inv = 1 mod 2**4
        // If denominator is zero the inverse starts with 2
        uint256 inv = 3 * denominator ^ 2;
        // Now use Newton-Raphson itteration to improve the precision.
        // Thanks to Hensel's lifting lemma, this also works in modular
        // arithmetic, doubling the correct bits in each step.
        inv *= 2 - denominator * inv; // inverse mod 2**8
        inv *= 2 - denominator * inv; // inverse mod 2**16
        inv *= 2 - denominator * inv; // inverse mod 2**32
        inv *= 2 - denominator * inv; // inverse mod 2**64
        inv *= 2 - denominator * inv; // inverse mod 2**128
        inv *= 2 - denominator * inv; // inverse mod 2**256
        // If denominator is zero, inv is now 128
        
        // Because the division is now exact we can divide by multiplying
        // with the modular inverse of denominator. This will give us the
        // correct result modulo 2**256. Since the precoditions guarantee
        // that the outcome is less than 2**256, this is the final result.
        // We don't need to compute the high bits of the result and prod1
        // is no longer required.
        result = prod0 * inv;
        return result;
    }
}

这个例程包含在 Uniswap V3FullMath.sol中,它可以在每笔交易中节省 gas。它也可以在OpenZeppelin和其他各种项目中找到。

上述的一个早期变体被简要地考虑包含在0x 协议 v2中。米哈伊尔·弗拉基米罗夫独立地将各个部分拼凑起来并提出了相同的策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/174982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】6.5 图的遍历

文章目录遍历定义深度优先搜索(DFS)算法步骤邻接矩阵上的遍历邻接矩阵深度优先算法DFS算法效率分析广度优先搜索(BFS)邻接表的广度优先算法BFS算法效率分析DFS与BFS算法效率比较遍历定义 和树的遍历类似&#xff0c;图的遍历也是从图中的某一个顶点出发&#xff0c;按照某种方法…

UPS BP650CH实现nas自动关机

家里有个自己拼凑的nas需要防止断电不正常关机&#xff0c;因此购买了施耐德后背式BP650CH&#xff0c;之所以选这款是因为带了串口&#xff0c;串口终究还是很方便的东西。不管linux还是window还是其他系统都能够使用&#xff0c;通过串口直接获得ups的信息&#xff0c;就不需…

JDBC Maven MyBatis

文章目录JDBC&#xff08;Java Database Connectivity&#xff09;入门API详解DriverManger&#xff08;驱动管理类&#xff09;Connection(数据库连接对象)作用StatementResultSet&#xff08;结果集对象&#xff09;PreparedStatement连接池MavenMaven模型Maven 常用命令依赖…

简单二叉树的介绍

1.树的结构&#xff08;了解&#xff09;1.1概念树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0)个有限节点总成一个具有层次关系的集合。把它叫做树是因为它看起来像一颗倒挂的树&#xff0c;也就是说它的根是朝上&#xff0c;而叶子是朝下的&#xff08;本人…

工作玩手机识别监测系统 YOLOv5

工作玩手机识别监测系统通过YOLOV5网络深度学习算法模型对画面中人员玩手机行为进行实时监测&#xff0c;当识别到有人在玩手机行为时&#xff0c;无需人为干预立即抓拍存档触发告警。YOLO算法- YOLO算法是一种基于回归的算法&#xff0c;它不是选择图像中有趣的部分&#xff0…

WT588D语音芯片介绍

WT588D语音芯片简介WT588D 语音芯片是一款功能强大的可重复擦除烧写的语音单片机芯片。WT588D 让语音芯片不再为控制方式而寻找合适的外围单片机电路&#xff0c;高度集成的单片机技术足于取代复杂的外围控制电路。配套WT588DVoiceChip 上位机操作软件可随意更换WT588D 语音单片…

基于 docker 搭建 mysql5.7 主从复制

安装 docker 的教程可以看我的另一篇文章&#xff0c;拉取 mysql 镜像的步骤也在里面&#xff0c;在这不再重复&#xff1a;https://blog.csdn.net/wanzijy/article/details/128695674 1. 主机搭建 因为本人虚拟机中已经存在了 mysql &#xff0c;所以在使用镜像创建容器的时…

【论文翻译】End-to-End Human Pose and Mesh Reconstruction with Transformers

【cvpr论文】End-to-End Human Pose and Mesh Reconstruction with Transformers (thecvf.com) 【github】microsoft/MeshTransformer: Research code for CVPR 2021 paper "End-to-End Human Pose and Mesh Reconstruction with Transformers" (github.com) 摘要 我…

学习笔记:Java 并发编程③

若文章内容或图片失效&#xff0c;请留言反馈。 部分素材来自网络&#xff0c;若不小心影响到您的利益&#xff0c;请联系博主删除。 视频链接&#xff1a;https://www.bilibili.com/video/av81461839配套资料&#xff1a;https://pan.baidu.com/s/1lSDty6-hzCWTXFYuqThRPw&am…

在甲骨文云容器实例(Container Instances)上部署Ubuntu Desktop

甲骨文云推出了容器实例&#xff0c;这是一项无服务器计算服务&#xff0c;可以即时运行容器&#xff0c;而无需管理任何服务器。 今天我们尝试一下通过容器实例部署Ubuntu Bionic Desktop。 创建容器实例 在甲骨文容器实例页面&#xff0c;单击"创建容器实例"&…

Java 笔试题

Java 笔试题目录概述需求&#xff1a;设计思路实现思路分析1.java 面试题参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challenge Surviv…

分享151个PHP源码,总有一款适合您

PHP源码 分享151个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 151个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/1T_Hs4j0t39b-Y8UWHmAKyw?pwd7ao0 提取码&#…

论文浅尝 | DB4Trans:数据库内置知识图谱嵌入模型训练引擎

笔记整理&#xff1a;柳鹏凯&#xff0c;天津大学硕士发表期刊&#xff1a;计算机学报 第45卷Vol.45, 第9期 No.9链接&#xff1a;http://cjc.ict.ac.cn/online/onlinepaper/lpk-202297212908.pdf动机知识图谱嵌入技术主要将知识图谱中的实体和关系嵌入到连续的向量空间中&…

Centos Java1.8+Nginx+redis+pgsql 手工配置

一、系统升级&#xff0c;安装系统常用工具及配置 1.1 升级软件及Centos 内核 yum update -y yum clean all cat /etc/redhat-release 1.2 安装虚拟机守护进程 yum install qemu-guest-agent -y 1.3 安装系统常用工具包 yum install lrzsz vim wget dnf -y 1.4关…

2023牛客寒假算法基础集训营3 -- E-勉强拼凑的记忆(贪心 + 二分)

题目如下&#xff1a; 题解 or 思路&#xff1a; 我们可以发现&#xff1a;除了 n2n 2n2 无解&#xff0c; 其他情况答案至少为 n12\frac{n 1}{2}2n1​ 答案在 n12\frac{n 1}{2}2n1​ 到 nnn 之间 我们可以假设 答案为 ansansans 最优摆放为&#xff1a; 所以可以二分去求…

软件工程 黄金点游戏

这个故事最初出现在 《移山之道》中&#xff0c;我经常拿来做和创新的时机相关课堂练习和讨论&#xff0c;效果很好。我把这个练习和它的一些延伸话题都搬到这个新博客里。 黄金点游戏 N个同学&#xff08;N通常大于10&#xff09;&#xff0c;每人写一个 0~100之间的有理数 …

1、认识IntelliJ IDEA

文章目录1、认识IntelliJ IDEA1.1 JetBrains公司介绍1.2 IntelliJ IDEA介绍1.3 IDEA的主要优势&#xff08;对比Eclipse&#xff09;1.3.1 功能强大1.3.2 符合人体工程学1.4 IDEA的下载【尚硅谷】idea实战教程-讲师&#xff1a;宋红康 生活是属于每个人自己的感受&#xff0c;不…

Python:Docx文档模板创建使用

✨博文作者 wangzirui32 &#x1f496; 喜欢的可以 点赞 收藏 关注哦~~ &#x1f449;本文首发于CSDN&#xff0c;未经许可禁止转载 &#x1f60e;Hello&#xff0c;大家好&#xff0c;我是wangzirui32&#xff0c;今天我们来学习Docx文档模板创建与使用&#xff0c;开始学习吧…

2023新春祝福html代码,包你学会

前言大家新年好&#xff01;今天是年三十&#xff0c;在这个充满喜悦和欢乐的节日里&#xff0c;祝大家新年快乐。不论你在外面过的风生水起还是不尽人意&#xff0c;回到家一家人团团聚聚才是最好的。进入正题&#xff0c;我们作为IT民工&#xff0c;我们要用自己的方式表达对…

第三天总结 之 商品管理界面的实现 之 页面中 下拉框问题的解决

页面中下拉框问题的解决 在页面中 点击商品类型这个图标 会出现下拉框 展示所有的商品类型 然后通过选择的 类型 来作为 查询时的一个条件 即 当不选或选择展示所有商品时 按照 不对这个条件进行操作 选择其他的商品类型时 会查询出含有该类型的商品 下拉框中 数据的展示与 如…