模2运算及模2运算式计算 (js)

概述

学习二维码生成的时候卡在纠错码部分,然后就接触到了伽罗华域,了解到模2运算,恰好前不久刚了解了波兰表达式,就尝试写一个支持模2运算的算式解析计算。

结果

'10011*101+101'.M2Calc() =>"1011010"

涉及内容

  • 模2运算
  • 波兰表达式(运算式解析)

实现

没有经过大量检测,如有问题请指正。
部分解读为个人理解,表述不会太标准。

异或xor(a,b)

mod2 加,减,乘,除都用到异或操作,js中的异或符^是将两侧内容看作10进值然后转成2进值异或,如下

'1001100' ^ '10011'  //1008023  错误
(parseInt('1001100',2)^parseInt('10011',2)).toString(2) //"1011111" 正确

因此不能直接使用此符进行异或,需要先转成十进值,运算完成后在再转回二进制字符串;或者也可以自定义二进制异或处理方式。
将异或作为公共方法

/*** 二进制字符串异或* @param bs0* @param bs1* @param type* @returns {string}*/
function xor(bs0, bs1, type = 1, resultLen) {//头部去0bs0 = bs0.replace(/^0+/, '');bs1 = bs1.replace(/^0+/, '');//多种方式进行异或//1) 异或符let result;if (type == 1) {result = (parseInt(bs0, 2) ^ parseInt(bs1, 2)).toString(2);}//2)自定义二进制字符串异或if (type == 2) {let maxLen = Math.max(bs0.length, bs1.length);bs0 = bs0.padStart(maxLen, '0');bs1 = bs1.padStart(maxLen, '0');let temp = '';for (let i = 0; (bs0[i] != null || bs1[i] != null); i++) {temp += (bs0[i] || 0) ^ (bs1[i] || 0)}result = temp.replace(/^0+/, '');}return resultLen ? result.padStart(resultLen, '0') : result
}

加法 M2Add(a,b)

mod2 加法定义为0+0=0 ;0+1=1 ; 1+0=1 ; 1+1=0;实际上就是二进制的异或

/*** 模2加法 等于异或* * @param bs0* @param bs1* @returns {string}*/
function M2Add(bs0, bs1) {return xor(bs0, bs1,1)
}

减法 M2Sub(a,b)

mod2 减法定义为 0-0=0 ; 0-1=1; 1-0=1; 1-1=0;实际上也是二进制的异或

/*** 模2减法  等于 异或* * @param bs0* @param bs1* @returns {string}*/
function M2Sub(bs0, bs1) {return xor(bs0, bs1,1)
}

乘法M2Pow(a,b)

M2Pow('10011','101') =>"1011111"

    10011
X     101
---------10011  组1 (这里标注'组'与下方乘法函数中的注释对应)100112
---------1011111
/*** 模2乘法* @param bs0 乘数  头部去零* @param bs1 乘数 头部去零* @returns {string}  如果输入的乘数头部不为零,则输出结果头部也不为零*/
function M2Pow(bs0, bs1) {let arr = [];//保存每一组乘数结果for (let i = 0; i < bs1.length; i++) {if (bs1[i] == '1') {arr.push(bs0 + ''.padStart(i, '0')) //补零}}//累计求和,不直接调用模2加,采用更直接的方式return arr.reduce((a, b) => xor(a, b,1), '0');
}

除法(取商) M2Div(a,b)

M2Div('1011010','10011') => "101"

/*** 模2 取商运算* @param bs0* @param bs1* @returns {string}*/
function M2Div(bs0, bs1) {//TODO 可以使用查表优化的,但是要分情况,所以暂时不用let fastDict = {'11': '0101','10': '0110','01': '0010','00': '0000',};//头部去0操作bs0 = bs0.replace(/^0+/, '');bs1 = bs1.replace(/^0+/, '');let bs1_len = bs1.length;//被除数根据除数的长度分为两部分,第一部分长度为除数长度let p0 = bs0.substr(0, bs1_len);let p1 = bs0.substr(bs1_len).split('');//每次相除只要余数长度(头部去零之后的长度)大于等于除数,就可以继续进行下一轮运算let quo = '';while (p0.length >= bs1_len) {//第一部分的首位为0,则与0 模2减,否则与除数模2减quo += p0[0];p0 = xor(p0, p0[0] == '0' ? '0': bs1,1,bs1_len);//首位除0p0 = p0.replace(/^0/, '');//从p1头部获取一位if (p1.length) {p0 += p1.shift()}}return quo.replace(/^0+/, '');
}

取模M2Mod(a,b)

其实是取商运算的简化,不用对商做维护;
M2Mod('1011010','10011') => "101"

             101---------10011 丿101101010011------0101100000-----1011010011------101
/*** 模2 取余运算,没有余数返回 ''* @param bs0 被除数* @param bs1 除数* @returns {string}*/
function M2Mod(bs0, bs1) {let fastDict = {'11': '0101','10': '0110','01': '0010','00': '0000',};//头部去0操作bs0 = bs0.replace(/^0+/, '');bs1 = bs1.replace(/^0+/, '');let bs1_len = bs1.length;//被除数根据除数的长度分为两部分,第一部分长度为除数长度let p0 = bs0.substr(0, bs1_len);let p1 = bs0.substr(bs1_len).split('');//每次相除只要余数长度(头部去零之后的长度)大于等于除数,就可以继续进行下一轮除法while (p0.length >= bs1_len) {//第一部分的首位为0,则与0 模2减,否则与除数模2减p0 = xor(p0, p0[0] == '0' ? '0': bs1,1,bs1_len);//首位除0p0 = p0.replace(/^0/, '');//从p1头部获取一位if (p1.length) {p0 += p1.shift()}}return p0.replace(/^0+/, '');
}

运算式M2Calc(str)

使用逆波兰表达式计算

'10011*101+101'.M2Calc() =>"1011010"


/***判断是 运算符|操作数|括号*@return 1:操作数 2:括号 3:运算符*/
function typeChk(d) {return /[01]+/.test(d) ? 1 : (/[\(\)]/.test(d) ? 2 : 0) //操作数返回1
}/*** 处理输入* 1) 替换中英括号* 2) 去除空格* 4) 返回字符分割*/
function dealStr(str) {return str.replace(//, '(').replace(//, ')').replace(/[^01\(\)\+\-\*\/%]/g, '').match(/([01]+)|\(|\)|\+|\-|\*|\/|%/g)
}/*** 模2算式计算  + - * /(取商) %(取模)* 使用逆波兰表达式* @param str*/
function M2Calc(str) {//一般的算数表达式即为中缀表达式str = str || "10011 * 101";//这里可以不用加默认组织//运算符权重let sdw = {'+': 1, '-': 1, '*': 2, '/': 2, '%': 2};//运算符转模2计算let fnDict = {'+': M2Add, '-': M2Sub, '*': M2Pow, '/': M2Div, '%': M2Mod};//循环安全数let saveCircle = 50;let operand = [];//操作数栈let operator = [];//操作符栈//去空格(主要是避免数字被空格拆分),分割成数组let arr = dealStr(str);//按照规则入栈let type;for (let i = 0, curr; (curr = arr[i]) != null; i++) {type = typeChk(curr);if (type == 1) {operand.push(+curr)} else if (type == 0) {let si = 0, stackTop;while (true && si++ < saveCircle) {stackTop = operator[operator.length - 1];if (stackTop == null || stackTop == '(') {operator.push(curr);break;} else if (sdw[curr] > sdw[stackTop]) {operator.push(curr);break;} else {operand.push(operator.pop())}}} else {if (curr == '(') {operator.push(curr)} else {let s, si = 0;while (s != '(' && si++ < saveCircle) {s = operator.pop();if (s == '(') {break;} else {operand.push(s)}}}}}//将操作符栈中剩下的弹出压入操作数栈let prevStack = [...operator, ...operand.reverse()];//计算let resultStack = [], left, right;for (let i = prevStack.length - 1, curr; (curr = prevStack[i]) != null; i--) {if (typeChk(curr)) {//是操作数resultStack.push(curr)} else {//是操作符  注意这里right/left 和后缀是相反地,先出的是右right = resultStack.pop();left = resultStack.pop();resultStack.push(fnDict[curr](left + '', right + ''))}}// console.log(prevStack);// console.log(resultStack);return resultStack.length != 1 ? '表达式有误' : resultStack[0]
}
//绑定到字符串
String.prototype.M2Calc = function(){return M2Calc(this)
};

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

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

相关文章

react配合python_部署React前端和Django后端的3种方法

Python部落(python.freelycode.com)组织翻译&#xff0c;禁止转载&#xff0c;欢迎转发。2020年4月7日星期二&#xff0c;马修西格尔类别&#xff1a;Django如果您要用Django REST开发web应用程序后端&#xff0c;并使用React或Vue开发应用程序前端。有很多方法实现。你需要做出…

伽罗瓦域(256) 生成指定纠错码字的生成多项式 (js)

效果 使用 复制code 保存为html 涉及内容 1、有限域、伽罗瓦域(256) 2、对数反对数 3、XOR 异或 两个因式各项相乘&#xff0c;当系数项相乘时&#xff0c;指数相加并mod(255) 合并同类项时&#xff0c;相同项的系数合并为 XOR操作&#xff1b; 伽罗瓦域依旧有些犯懵&…

python贪心算法求删数问题_贪心算法删数问题

删数问题给定n位正整数a&#xff0c;去掉其中任意k个数字后&#xff0c;剩下的数字按原次序排列组成一个新的正整数。对于给定的n和k&#xff0c;设计一个算法&#xff0c;找出剩下数字组成的新数最少的删数方案。输入示例&#xff1a; 178543 4输出&#xff1a; 13输入示例&am…

二维码-纠错码生成(js)

概要 本文主要为计算&#xff0c;而非对伽罗瓦域等数学内容的深入解析&#xff0c;在知道消息多项式以及纠错数量的情况下通过程序生成对应的纠错码。详细的二维码生成原理参考一个详细全面的二维码生成解析 效果 数据码: 长度16的示例数据码&#xff08;正常获取的是示例的…

一步一步学python爬虫_初学Python之爬虫的简单入门

初学Python之爬虫的简单入门一、什么是爬虫&#xff1f;1.简单介绍爬虫爬虫的全称为网络爬虫&#xff0c;简称爬虫&#xff0c;别名有网络机器人&#xff0c;网络蜘蛛等等。网络爬虫是一种自动获取网页内容的程序&#xff0c;为搜索引擎提供了重要的数据支撑。搜索引擎通过网络…

实现二维码-完整三种编码流程加代码解析(javascript)

效果 输入内容&#xff1a;XXXwedewed生日//&sss乐❤XXXwedewed生日//&sss乐❤ 完整的演示效果为&#xff0c;输入内容后会将解码绘制的每一步都展示&#xff08;有点长就不全截图了&#xff0c;可以直接移至最后复制代码到本地运行&#xff09;&#xff1a; 原理…

可视化排班管理_小白经理的思考日记-可视化看板和走动管理

前言&#xff1a;所谓勤于思&#xff0c;敏于行&#xff0c;实践能提升思考的深度&#xff0c;反思也能更好的指导实践。基于这样的认知&#xff0c;我将过往所学所思所行进行了专题整理&#xff0c;对内化知识和技能结构颇有益。又承蒙付老师抬爱和鼓励&#xff0c;推荐我看《…

headerIP php_PHP curl伪造IP地址和header信息代码实例

原标题&#xff1a;PHP curl伪造IP地址和header信息代码实例curl虽然功能强大&#xff0c;但是只能伪造$_SERVER["HTTP_X_FORWARDED_FOR"]&#xff0c;对于大多数IP地址检测程序来说&#xff0c;$_SERVER["REMOTE_ADDR"]很难被伪造&#xff1a;首先是clien…

c++ 使用nacos_为什么选用Nacos?虎牙直播微服务改造实践

原标题&#xff1a;为什么选用Nacos&#xff1f;虎牙直播微服务改造实践“相比文字和图片&#xff0c;直播提供了人与人之间更丰富的沟通形式&#xff0c;其对平台稳定性的考验很大&#xff0c;那么倡导“以技术驱动娱乐”的虎牙直播如何在技术上赋能娱乐&#xff1f;本文将分为…

three.js 拖动场景中物体(原生|拖拽控制器)

非控制器版 拖动场景中的物体实际上是在一个平行于窗口的平面中进行拖动&#xff0c;确定这个平面并确定鼠标在该平面中的位置变化&#xff0c;就将问题转换成简单的2d移动物体了 <!DOCTYPE html> <html> <head><meta charsetutf-8><title>015-…

bch纠错码 码长8_从HDMI视频数据带有BCH纠错码讨论线材对画质的影响

一直感觉几十元的HDMI线已经可以正常传输视频信号,那么几百元应该是接近完美了,再听人说换上几千块的线就让画质黑位什么的提升一大截,认为非常不可思议.但别人又信誓旦旦的说自己是感觉到了明显改变,对这种情况产生的争论最终不会得到正确答案,所以数据党还是从科学的角度先分…

element-ui 可复选树型表格

效果 思路 自定义模板当点击某个行复选框时&#xff0c;其所有后代复选框都要同步状态&#xff0c;且其直系父辈状态需要根据所点击复选框的状态来修正点击全选复选框时&#xff0c;批量同步所有行内复选框状态 代码 非封装组件&#xff0c;按需自行改写 确保引入element-ui…

linux 删除含有关键词的文件_linux下查找包含关键字的文件

在linux下如果要查找包含某个关键字的文件&#xff0c;如要在nagios目录下搜索带有关键字“store-rd-sys”的文件&#xff0c;在终端下运行命令&#xff1a;/usr/local/nagios/etc/* (nagios目录)法1&#xff1a;grep -r “关键字” 路径[rootnagios01 ~]#grep -r "store-…

树形可拖拽排序配置组件

效果 使用场景 vue2下自定义表格表头配置: 列排序&#xff0c;显示/隐藏等。确保表头以配置项的形式加载&#xff0c;这样表格才能对修改后的配置作响应 思路 1、表格使用render函数加载(如有疑问可私信)&#xff0c;通过类似如下的columns配置表头 columns: [{ label: 姓名…

maven 打包指定依赖包_Maven打包成Jar文件时依赖包的问题

我们项目中使用到第三方的库文件&#xff0c;这些jar库文件并没有放到Maven中央库上&#xff0c;导致我们需要在项目中自己配置使用。我们的两三个开发人员对Java都是很熟&#xff0c;因此在使用中遇到了一些问题&#xff0c;表现在&#xff1a;在本地中引入第三方jar包后&…

自适应浮动表单填充布局脚本

效果 1、适合搜素表单布局&#xff0c;查询重置等功能块始终位于最后一行的最后一列 2、适合普通多行两端对齐&#xff0c;未填充满的行左对齐 思路 此脚本目的为实现整齐风格的表单布局&#xff0c;为了达到整齐的效果&#xff0c;每个表单元素或者块都要设置一致的 宽度…

rstudio导入txt文件_R语言 | 读写txt、csv、excel文件

前段时间看到plotnine库(封装的R语言ggplot2)作的图太美了&#xff0c;有点想重新拾起R语言^_^R语言代码略带凌乱&#xff0c;讲真的还是更喜欢Python代码简洁。不过好几年不琢磨R语言&#xff0c;对R语言代码的凌乱美有些新奇&#xff0c;很好玩&#xff0c;这也许就是久别胜新…

erp采购总监个人总结_erp采购总监总结.docx

erp采购总监总结ERP沙盘模拟心得体会——采购总监  刚开始接触ERP&#xff0c;就从学长们那里了解到这门课比较有意思&#xff0c;然后又听老师说我们还有一个为期两周的ERP沙盘模拟&#xff0c;这让我对这门课更有了极大的兴趣。一直期待着沙盘模拟对抗早点到来&#xff0c;…

矩阵字符串配置任意合并表格布局

效果 核心 布局配置矩阵&#xff08;以下为多个模式),可以使用|或\n表示矩阵行 const gridArr [1,2,a,b 3,4,a,b 5,6,a,b ,1,2 3,4 5,6 ,1,2,3,4 3,4]任意横向或者纵向相同的字符表示一个合并块 使用 <CalcTable grid"1,2,a,b|3,4,a,b|5,6,a,b" ><span…