Solidity 中的数学(第 1 部分:数字)

news2024/12/26 14:28:04

本文开启了一系列关于在 Solidity 中进行数学运算的文章。第一个要讨论的话题是:数字

 

介绍

以太坊是一个可编程的区块链,其功能可以通过将称为智能合约的可执行代码片段发布到区块链本身来扩展。这将以太坊与第一代区块链区分开来,在第一代区块链中,新功能需要修改客户端软件、升级节点以及分叉整个区块链。

智能合约是在链上发布的一段可执行代码,分配有唯一的区块链地址。智能合约控制属于其地址的所有资产,并在与其他智能合约交互时可以代表该地址进行操作。每个智能合约都有持久存储,用于保存调用之间的智能合约状态。

Solidity是以太坊以及其他几个使用以太坊虚拟机 (EVM) 的区块链平台上智能合约开发的主要编程语言。

编程总是关于数学的,区块链总是关于金融的,金融自古就是关于数学的(或者也许数学就是关于金融的)。作为以太坊区块链的主要编程语言,Solidity 必须做好数学运算。

在本系列中,我们讨论了 Solidity 如何进行数学运算的各个方面,以及开发人员如何在 Solidity 中进行数学运算。第一个要讨论的话题是:数字

Solidity 中的数值类型

与主流编程语言相比,Solidity 的数值类型相当多:即 5,248。是的,根据文档,有 32 种有符号整数、32 种无符号整数、2592 种有符号定点和 2592 种无符号定点类型。JavaScript 只有两种数字类型。Python 2 曾经有四个,但在 Python 3 中删除了“long”类型,所以现在只有三个。Java 有七个,C++ 大约有十四个。

有这么多数字类型,Solidity 应该有适合每个人的类型,对吧?没那么快。让我们仔细看看这些数字类型。

我们将从以下问题开始:

为什么我们需要多种数值类型?

剧透:我们没有。

纯数学中没有数字类型。一个数可能是整数或非整数,有理数或无理数,正数或负数,实数或虚数等,但这些只是属性,数字可能有也可能没有,单个数字可能同时具有多个这样的属性。

许多高级编程语言都有单一的数字类型。在 2019 年引入“BigInt”之前,JavaScript 只有“数字”。

除非做硬核低级的东西,否则开发人员并不真正需要多种数字类型,他们只需要具有任意范围和精度的纯数字。然而,这些数字本身不受硬件支持,并且在软件中模拟有些昂贵。

这就是为什么低级编程语言和以高性能为目标的语言通常具有多种数值类型,例如有符号/无符号,8/16/32/64/128位宽,整数/浮点数等。这些类型是原生支持的硬件,广泛用于文件格式、网络协议等,因此低级代码从中受益。

然而,出于性能原因,这些类型通常会继承底层 CPU 指令的所有奇怪语义,例如静默溢出和下溢、不对称范围、二进制分数、字节顺序问题等。这使得它们在高级业务逻辑代码中很痛苦。直接使用通常显得不安全,而安全使用通常变得麻烦且不可读。

那么,下一个问题是:

为什么 Solidity 有这么多数值类型?

剧透:它没有。

EVM 原生支持两种数据类型:256 位字和 8 位字节。堆栈元素、存储键和值、指令和内存指针、时间戳、余额、交易和块哈希、地址等都是 256 位字。内存、字节码、调用数据、返回数据都是由字节组成的。大多数 EVM 操作码都处理单词,包括所有数学运算。一些数学运算将单词视为有符号整数,一些作为无符号整数,而其他运算只是以相同的方式工作,而不管参数是否在无符号上签名。

所以 EVM 原生支持两种数值类型:有符号 256 位整数和无符号 256 位整数。这些类型在 Solidity 中分别称为intuint

除了这两种类型(以及它们的别名int256uint256)之外,Solidity 有 62 种整数类型int<N>,和uint<N>,其中<N>可以是 8 到 248 之间的任意 8 的倍数,即 8、16、…、248。在 EVM 级别上,所有这些类型都由相同的 256 位字,但每个操作的结果都被截断为 N 位。它们可能对特定情况有用,当需要特定位宽时,但对于一般计算,这些类型只是功能较弱且效率较低(在每个操作后截断不是免费的)版本intuint.

最后,Solidity 有 5184 种定点类型fixedNxMufixedNxM其中 N 是从 8 到 256 的 8 的倍数,N 是从 0 到 80 的整数。这些类型应该实现各种范围和精度的十进制定点算术,但截至目前(Solidity 0.6.2)文档说:

Solidity 尚未完全支持定点数。它们可以声明,但不能分配给或分配自。

因此目前一般不支持定点数和分数数。

那么,下一个问题是:

如果我们需要大于 256 位的小数或整数怎么办?

剧透:你必须效仿他们。

有人会说,256 位应该对任何人都足够了。然而,一旦以太坊中的大多数数字都是 256 位宽,那么即使简单的两个数相加也可能有 257 位宽,而两个数的乘积可能高达 512 位宽。

模拟比编程语言本身支持的类型更宽的固定或可变宽度整数的常见方法是将它们表示为固定或可变长度的较短的、本机支持的整数序列。因此,宽整数的位图是较短整数的位图的串联。

在 Solidity 中,宽整数可以表示为固定或动态数组,其元素是字节或uint值。

对于分数,情况有点复杂,因为它们有不同的风格,每种都有自己的优点和缺点。

最基本的是简单分数:只有一个整数,称为“分子”,除以另一个整数,称为“分母”。在 Solidity 中,简单分数可以表示为一对两个整数,也可以表示为一个整数,其位图是分子和分母位图的串联。在后一种情况下,分子和分母必须具有相同的宽度。

另一种流行的分数格式是定点数。定点数基本上是一个简单的分数,其分母是一个预定义的常数,通常是 2 或 10 的幂。前一种情况称为“二进制”定点,而后者称为“十进制”定点。只要分母是预定义的,就不需要明确指定,所以只需要指定分子。在 Solidity 中,定点数通常表示为单个整数分子,而常用的分母是 10¹⁸、10²⁷、2⁶⁴ 和 2¹²⁸。

另一种众所周知的小数格式是浮点数。基本上,浮点数可以描述如下:

其中m(尾数)和e(指数)是整数,B(基数)是预定义的整数常量,通常为 2 或 10。B =2 的情况称为“二进制”浮点数,B = =10 被称为“十进制”浮点数。

IEEE-754标准化了几种常见的浮点格式,包括称为“半”、“单”、“双”、“四倍”和“八倍”精度的五种二进制格式。这些格式中的每一种都将尾数和指数打包成分别为 16、32、64、128 或 256 位的单个序列。在 Solidity 中,这些标准格式可以用二进制类型bytes2bytes4bytes8bytes16和表示bytes32。或者,尾数和指数可以分别表示为一对整数。

这部分的文件问题:

我们必须自己实施这一切吗?

剧透:没有必要。

好消息是,有各种数字格式的 Solidity 库,例如:fixidity(具有任意小数位数的十进制定点)、DSMath(具有 18 位或 27 位小数的十进制定点)、BANKEX 库(IEEE-754 八元组精度浮点数)、ABDK 库(二进制定点数和四倍精度浮点数)等。

坏消息是不同的库使用不同的格式,所以很难将它们结合起来。这个问题的根源将在下一节中讨论。

Solidity 中的数字文字

在上一节中,我们讨论了数字在运行时是如何表示的。在这里,我们将看看它们在开发时是如何表示的,即在代码本身中。

与主流语言相比,Solidity 具有相当丰富的数字字面量语法。首先,支持良好的旧十进制整数,例如42. 与其他类 C 语言一样,有十六进制整数文字,如0xDeedBeef. 到目前为止,一切都很好。

在 Solidity 中,文字可能有单位后缀,例如6 ether, 或3 days。一个单位,基本上就是一个因数,字面意思是乘以。这ether是 10¹⁸ 和days86,400(24 小时 × 60 分钟 × 60 秒)。

除此之外,Solidity 还支持整数文字的科学记数法,例如2.99792458e8. 这很不寻常,因为主流语言仅支持小数文字的科学记数法。

但可能整个 Solidity 语言最独特的功能是它对有理文字表达式的支持。实际上每个成熟的编译器都能够在编译时计算常量表达式,因此x = 2 + 2不生成add操作码,而是等同于x = 4. Solidity 也能做到这一点,但实际上,它远远不止于此。

在主流语言中,常量表达式的编译时求值只是一种优化,因此常量表达式在编译时的求值方式与在运行时的求值方式完全相同。这使得可以用具有相同值的命名常量或变量替换此类表达式的任何部分,并获得完全相同的结果。然而,对于 Solidity 来说,情况并非如此。

在运行时,Solidity 循环中的除法结果趋向于零,其他算术运算在溢出时回绕,而在编译时,使用具有任意大分子和分母的简单分数计算表达式。因此,在运行时,表达式((7 / 11 + 3 / 13) * 22 + 1) * 39将被计算为 39,而在编译时,相同的表达式被计算为 705。不同之处在于,在运行时,7 / 113 / 13被四舍五入为零,但在编译时,整个表达式被计算在简单的分数中,根本没有任何四舍五入。

更有趣的是,以下表达式在 Solidity 中是有效的:7523 /48124631 * 6397,而这不是有效的:7523 / 48125631 * 6397。不同之处在于前者评估为整数,而后者评估为非整数。请记住,Solidity 在运行时不支持分数,因此所有文字都必须是整数。

虽然小数和大整数可以在运行时在 Solidity 中表示,如前几节所述,但没有方便的方法在代码中表示它们。这使得使用此类数字执行操作的任何代码都相当神秘。

只要 Solidity 没有标准的定点或浮点格式,每个库都使用自己的格式,这使得库彼此不兼容。

结论

智能合约从以太坊区块链诞生之初就开始计算。从简单的百分比到复杂的衍生品估值。然而,智能合约开发的主要语言 Solidity 在数学方面并没有走得更远,只是揭示了 EVM 操作码能够做什么。

图书馆试图弥补基本语言遗漏的内容,但缺乏标准化的数字格式。

核心语言有一些无与伦比的特性,但同时缺乏对基本的、必备的东西的支持。

在后续的文章中,我们将讨论如何处理这一切,下一个要讨论的话题就是:溢出

 

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

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

相关文章

PointNet.pytorch点云三维深度学习论文与代码复现

PointNet.pytorch1. 概要1.1 文章1.2 点云和三维深度学习&#xff0c;PointNet 网络结构1.3 复现说明2. 代码2.1 代码逻辑2.2 思路详解3. 解析组会2023.1.18远程arcivdailyonedb1. 概要 1.1 文章 链接: 论文 1.2 点云和三维深度学习&#xff0c;PointNet 网络结构 链接: 三…

程序员必备素质:代码整洁之道

本次分享的内容是《代码整洁之道》&#xff0c;书中是以现实案例&#xff0c;以讲故事形式来总结归纳问题&#xff0c;并给出解决方案&#xff0c;很容易与我们产生共鸣。文中会有大量书中内容摘抄&#xff0c;都是个人认为很值得分享的内容。当然&#xff0c;也会有个人感悟&a…

【C++】从0到1入门C++编程学习笔记 - 基础入门篇:C++初识

文章目录一、第一个C程序1.1 创建项目1.2 创建文件1.3 编写代码1.4 运行程序二、注释三、变量四、常量五、关键字六、标识符命名规则一、第一个C程序 编写一个C程序总共分为4个步骤 创建项目创建文件编写代码运行程序 1.1 创建项目 Visual Studio是我们用来编写C程序的主要…

【C语言课程设计】通讯录(2.0版本)

前言 在前面的博客中&#xff0c;我们已经了解了通讯录的基本写法。当然那个通讯录是不够完善的。我们本小节对前面的通讯录做一次小升级&#xff0c;添加动态增容模块与利用枚举来优化选择语句 【C语言课程设计】通讯录&#xff08;1.0版本&#xff09;_青色_忘川的博客-CSDN博…

JVM-内存模型详解

JVM 把内存分为若干个不同的区域&#xff0c;这些区域有些是线程私有的&#xff0c;有些则是线程共享的&#xff0c;Java 内存区域也叫做运行时数据区&#xff0c;它的具体划分如下&#xff1a; 虚拟机栈 Java 虚拟机栈是线程私有的数据区&#xff0c;Java 虚拟机栈的生命周期…

word查看技巧:如何快速找到文档的修改痕迹

不知道大家在工作中有没有遇到过这类的工作场景&#xff1a;当初步拟好一份合作协议或是项目策划书后&#xff0c;发给老板或其他同事审阅和修订&#xff0c;通常会不断地来回修改文档。此时&#xff0c;如果你想要查看文档哪里被修改过&#xff1f;你会怎么操作&#xff1f;很…

SpringBoot集成Elasticsearch7.4 实战(二)

1、前言本篇文章主要讲的是:在Springboot环境下&#xff0c;利用JAVA环境操作索引,集成SpringBoot等相关知识2. SpringBoot集成开发工具&#xff0c;这里选择的是IDEA 2019.2&#xff0c;构建Maven工程等一堆通用操作&#xff0c;不清楚的自行百度。2.1. POM配置我这边选择 ela…

协程应用——aiohttp异步爬虫实战

aiohttp异步爬虫实战1. 案例介绍2. 准备工作3. 页面分析4. 实现思路5. 基本配置6. 爬取列表页7. 爬取详情页8. 总结1. 案例介绍 本例要爬取的网站是https://spa5.scrape.center/,数据量相对大&#xff0c;所以用到了异步爬虫&#xff0c;主要学习这种方法是如何提高效率的。网…

Maven学习(三):纯手撸一个Maven项目

纯手撸一个Maven项目一、创建Maven工程目录二、Maven项目构建命令三、插件创建工程1、创建java工程2、创建web工程3、对比java工程和web工程区别一、创建Maven工程目录 按照下图所示的结构创建项目所需文件夹&#xff1a; 在Demo.java文件内输入以下代码&#xff1a; package…

数据库被勒索删除,解决方法

突然数据库被黑了&#xff0c;有一条勒索信息: To recover your lost Database send 0.018 Bitcoin (BTC) to our Bitcoin address: bc1qe4yefrptv2k8shawu3h84j0n8kyvxfk4wwate5 After this, contact us by email with your Server IP or Domain Name and a Proof of Payment …

JavaScript中的严格模式

一.什么是严格模式 在ECMAScript5标准中&#xff0c;JavaScript提出了严格模式的概念&#xff1a; 严格模式是一种具有限制性的JavaScript模式&#xff0c;从而使代码隐式脱离了“懒散(sloppy)模式”&#xff1b;支持严格模式的浏览器在检测到代码中有严格模式时&#xff0c;…

卡方检验的基本原理详解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、卡方检验基本原理1. 1 χ2统计量计算公式1.2 理论频数如何计算&#xff1f;1.3 χ2值的结果如何理解&#xff1f;1.4 χ2检验的自由度如何理解&#xff1f;1.5 χ…

Arduino开发串口控制ESP8266 RGB LED

根据板卡原理RGB三色LED对应引脚&#xff1a;int LEDR12、int LEDG14、int LEDB13;设置串口波特率为115200Serial.begin(115200);源代码如下所示&#xff1a;/*名称&#xff1a;串口控制RGB亮灭实验功能&#xff1a;通过串口输入R、G、B三个字母来点亮对应的LED灯&#xff0c;关…

Java集合进阶——Map

一、Java Map集合详解 Map集合概述和特点 概述&#xff1a; 将键映射到值的对象 一个映射不能包含重复的键 每个键最多只能映射到一个值 Map接口和Collection接口的不同 Map是双列的,Collection是单列的 Map的键唯一,Collection的子体系Set是唯一的 Map集合的数据结构针对键有…

放假第三天

假期 # 生活 # 水文 咱们继续假期第三天的日常更文&#xff0c;没看上篇的铁子们我把地址贴在下面。 点我 虽然是假期&#xff0c;但我规划已久的睡懒觉流程却是一直执行不下去。这不今天早上八点我就起床了&#xff0c;当然起的早不是为了“卷”&#xff0c;而是吃早餐。说出…

Python操作 JWT(python-jose包)、哈希(passlib包)、用户验证完整流程

一、JWT简介 JWT是什么&#xff1f; JWT 即JSON 网络令牌&#xff08;JSON Web Tokens&#xff09;。 JWT(JSON Web Token) 是一种用于在身份提供者和服务提供者之间传递身份验证和授权数据的开放标准。JWT是一个JSON对象&#xff0c;其中包含了被签名的声明。这些声明可以是…

电脑开机出现绿屏错误无法启动怎么办?

电脑开机出现绿屏错误无法启动怎么办&#xff1f;有用户电脑开机的时候&#xff0c;突然出现了屏幕变成绿色的情况&#xff0c;而且上面有很多的错误代码。然后卡在页面上一直无法进入到桌面&#xff0c;重启电脑后依然无效。那么如何去解决这个问题呢&#xff1f;来看看具体的…

Java---Spring---SpringCache

SpringCache入门学习SpringCache介绍SpringCatch常用注解SpringCatch使用1.导入maven坐标2.配置application.yml3.在启动类上加入EnableCaching注解&#xff0c;开启缓存注解功能4.在controller的方法上加入Cacheable,CacheEvict等注解&#xff0c;进行缓存操作缓存穿透定义解决…

【Nginx】入门看这一篇就够啦,nginx 简介、安装、工作原理、工作方式、详解配置文件

目录 1、nginx 简介 2、nginx的工作原理 3、nginx 工作方式 4、nginx 安装 命令行安装 卸载命令 从源码构建 查看版本 测试启动 5、详解nginx配置文件 第一部分&#xff1a;全局块 第二部分&#xff1a;events块 第三部分&#xff1a;http 6、hosts 文件简介 1、…

解析Activity启动-窗口篇

解析Activity启动-窗口篇 在 解析Activity启动 前两篇文章中&#xff0c;我们分别专注于 堆栈 和 生命周期角度大致的过了一遍启动流程&#xff0c;而本篇会着重窗口的创建和显示流程&#xff0c;继续梳理Activity的启动流程 顺着前两篇文章的分析流程&#xff0c;我们知道和 …