平衡三进制小数详解与进制转换

news2024/12/23 11:34:48

        标准三进制是“逢三进一,退一还三”的机制,平衡三进制与之类似,但就是偏移了一下变得对称了,平衡三进制与标准三进制可以相互转换,但这样显得有点多余了,所以这里只讲平衡三进制与十进制的转换。

数字系统的由来

远古时代:原始人通过绳子系绳结、在石头或木头上刻划痕的方式来记数,这种计数方法简单,但难数,时间过久了就难以分清那个是那个了。

非位置化数字系统:罗马数字(经典代表),罗马数字共有7个,分别是Ⅰ(1)、Ⅴ(5)、Ⅹ(10)、Ⅼ(50)、Ⅽ(100)、Ⅾ(500)和Ⅿ(1000),若为ⅤⅤⅤ则表示15。

位置化数字系统:现在用的基本都是这个,如:二进制、平衡三进制、十进制等,计算金钱的用的也是位置化数字系统,它与我们的生活息息相关。

位置化系统的位权

        以小数点为分界线,整数的第一位为0,向前一位为1,再向前一位为2,依次类推;然后是小数部分,第一位为-1,向后一位为-2,再后一位为-3依次类推;位置化系统的位权作为系数,若基数为十,则称为十进制、若基数为2,则称为二进制、若基数为3,则称为标准三进制或平衡三进制,如下表所示:

位置化系统的位权210-1-2-3
十进制数(125.345)125.345
10^210^110^010^-110^-210^-3
平衡三进制数(1TT.111)1TT.111
3^23^13^03^-13^-23^-3

平衡三进制的小数表示

        这是一个绕不开的问题,要想搞明白平衡三进制的小数如何表示,怎么来的那就先搞懂十进制的小数与整数,如上表十进制数为125.345,也就是:

1*10^2 + 2*10^1 + 5*10^0 + 3*10^-1 + 4*10^-2 + 5*10^-3

=100 + 20 + 5 + 0.3 + 0.04 +0.005

=125.345

所以平衡三进制1TT.111(十进制5.5),可表示为:

1*3^2 + T*3^1 + T*3^0 + 1*3^-1 + 1*3^-2 + 1*3^-3

=9 + (-3) + (-1) + (1/3) + (1/9) + (1/27)

大概为5.4,要精确到后5位,这样的结果较为准确,1TT.11111重新计算结果为5.46095.

平衡三进制转换的运算规则

        平衡三进制作为标准三进制的一个变体,所以还是以标准三进制出发,然后再进一步去除得到最终的平衡三进制转换方法。

标准三进制转平衡三进制的方法

        平衡三进制的转转换法中,需要先写出一个给定的数 x 在标准三进制中的表示。当 x 是用标准三进制表示时,其数字的每一位都是 0、1 或 2。要转化为平衡三进制,需要从低位到高位操作

  1. 遇到 0 和 1,可直接跳过
  2. 遇到 2,当前位改为 T,向前进位加上 1
  3. 遇到 3,当前位改为 0,向前进位加上 1

十进制整数直接转平衡三进制的方法

    每次进行模3取余,最后进行倒序读取,有以下得余数表示,
    -2    -1    0    1    2(正数与负数分别对2与-2处理)
    -1、0、1合法的,故不处理
    若商为-2,则将商减一,再除于3得到新商,然后余数变成1
    若商为 2,则将商加一,再除于3得到新商,然后余数变成-1

        如上图所示,先用连除法,不断的除于3取余,商至到为0结束,标准三进制得到的数为20,然后用第一个规则(标三转平三),得到1T0;然后直接跳过标准三进制,当商为 2,则将商加一,再除于3得到新商为1,然后余数变成-1,直接得1T0,这样就不用转来转去了。

十进制小数直接转平衡三进制的方法

    每次进行乘3取整,正数结果为正,负数则为负,那么会有以下得整数表示,
    -2    -1    0    1    2(正数与负数分别对2与-2处理)
    若为正数,则遇到0或1直接跳过,遇到2当前位改T,向前进1
    若为负数,则遇到0或1直接跳过,遇到-2当前位改1,向前进T

        如上图所示,小数用的是连乘法,不断的乘于3取整,可以精确到某一位或为0为止,标准三进制得到0.3为0.022002,然后用第一个规则(标三转平三),得到0.10T01T;然后直接跳过标准三进制,遇到0或1直接跳过,遇到2当前位改T,向前进1,也就是向上进1,直接得到0.10T01T,得到正数直接可以(1变T,T变1)变为负数,也可以再算一次。

总结:

整数部分与小数部分要分开算,得到相应结果,最后再相加在一起就行了;

整数部分使用连除法,采用倒序读取余数,即可以得结果;

小数部分使用连乘法,采用正序读取整数,即可以得结果;

十进制浮点数转平衡三进制数的实现

        先观察上图,平衡三进制数,它的小数很有特点,就是以0.5或-0.5为分界,它过了这条界则要向前进一位,上面与下面的数也是对称,所以如果是4.5转成平衡三进制,则为11.11111111,当为4.6时,则0.6为1.TT11和4的11相加,则整数部分要进位,得到1TT.TT11TT11TT,其中小数部分没变,整数变了,所以当小数与整数合体时,大于0.5或小于-0.5的小数要进位,会丢失一位,所以要在前面补0就行了。

        然后结合上面的方法,十进制数的整数与小数分别转为平衡三进制,再将它们结合在一起就可以了,这里用C++成功实现了上述方法,采用的是deque容器数据结构,它可以高效的在前后两端推入数据,类似于数组但不是数组,因为要进位所以用deque容器,当输入去的数据再拿出来改时方便,平衡三进制的小数和它的分数其实都各有优势,但我更喜欢分数(方便计算,误差小)。

        平衡三进制和十进制一样,用小数点分隔整数部分和小数部分;在平衡三进制中,四舍五入和截位的操作是等效的;平衡三进制可以像十进制一样,可以用小数来表示分数;小数可分为:有限小数、无限循环小数、无限不循环小数,小数中除无限不循环小数外都可以用分数来表示;最后给出写了几天,终于写出的十进制浮点数转平衡三进制的C++代码:

#include <iostream>
#include <deque>
#include <algorithm>


using namespace std;
// 将deque容器内数据展示出来
void showDequeArray(const deque<char>& charDeque) {
    for (char element : charDeque) {
        cout << element;
    }
    cout << endl;
}
// 将数字转为char
char toTargetChar(int n) {
    switch (n) {
        case -1: return 'T';
        case 0:  return '0';
        case 1:  return '1';
        default: return '\0';
    }
}

//进位操作
void changeCarryChar(deque<char>& originBalancedTernary,char carryChar){
	//默认要进一位,倒着读取再进位
	bool isCarry=true;
	//当前最后一位为originBalancedTernary.size()-1,
	//前一位为originBalancedTernary.size()-2,
	//最后一位改写,前一位判断是否再进位,同样要改写
	for (int i = originBalancedTernary.size()-2; i >= 0; --i) {	
		//若false则不进位,结束循环
		if(!isCarry) break;
		//这是变换进位操作(正数进1,负数进T)
		switch (originBalancedTernary[i]) {
			case '0':
				isCarry=false;
				originBalancedTernary[i]=carryChar;
				break;
			case '1':
				if(carryChar=='T'){
					isCarry=false;
					originBalancedTernary[i]='0';
				}
				else if(carryChar=='1'){
					isCarry=true;
					originBalancedTernary[i]='T';
				}
				break;
			case 'T':
				if(carryChar=='1'){
					isCarry=false;
					originBalancedTernary[i]='0';
				}
				else if(carryChar=='T'){
					isCarry=true;
					originBalancedTernary[i]='1';
				}
				break;
			default:
				break;
		}
	}
}


//将十进制数转换成平衡三进制数
deque<char> decimalToBalancedTernary(double decimal){
	deque<char> balancedTernary;//创建 Vector存结果
	const int maxIterations = 10;//可调整,小数部分的精确位
	/*
	获取整数部分,进行转换操作,
	每次进行模3取余,因为会出现负数,那么会有以下得余数表示,
	-2	-1	0	1	2(正数与负数分别对2与-2处理)
	-1、0、1合法的,故不处理
	若商为-2,则将商减一,再除于3得到新商,然后余数变成1
	若商为 2,则将商加一,再除于3得到新商,然后余数变成-1
	*/
	int integerPart = static_cast<int>(decimal);
	if(integerPart==0)balancedTernary.push_back('0');//默认为0,则出0
    while (integerPart != 0) {
    	int remainder = integerPart % 3;//得到余数
    	switch (remainder) {
			case -1:
			case  2:
				balancedTernary.push_back('T');
				integerPart = (integerPart + 1) / 3;//商加一,除于3是为了得到商
				break;
			case  1:
			case -2:
				balancedTernary.push_back('1');
				integerPart = (integerPart - 1) / 3;//商减一,除于3是为了得到商
				break;
			default:
				balancedTernary.push_back('0');
				integerPart /= 3;//除于3是为了得到商
				break;
		}
    }
	reverse(balancedTernary.begin(), balancedTernary.end()); // 反转顺序,倒序读取
	
	balancedTernary.push_back('.');//添加小数点
	/*
	获取小数部分,进行转换操作,
	每次进行乘3取整,正数结果为正,负数则为负,那么会有以下得整数表示,
	-2	-1	0	1	2(正数与负数分别对2与-2处理)
	若为正数,则遇到0或1直接跳过,遇到2当前位改T,向前进1
	若为负数,则遇到0或1直接跳过,遇到-2当前位改1,向前进T
	*/
	double fractionalPart = decimal - static_cast<int>(decimal);
	//大于0.5或小于-0.5的小数要进位,当小数与整数合体时,会丢失一位,所以要在前面补0
	if(fractionalPart>0.5 || fractionalPart < -0.5)balancedTernary.push_front('0');
    for (int i = 0; i < maxIterations; ++i) {
		fractionalPart*=3;
		int roundIndex = static_cast<int>(fractionalPart);//乘3后取整的数
		switch (roundIndex) {
			case -2:
				balancedTernary.push_back('1');
				changeCarryChar(balancedTernary,'T');
			break;	
			case 2:
				balancedTernary.push_back('T');
				changeCarryChar(balancedTernary,'1');
			break;
			default:
				balancedTernary.push_back(toTargetChar(roundIndex));
				break;
		}
		fractionalPart-=roundIndex;//得到剩下的小数	
    	if (fractionalPart == 0) break;// 如果小数部分已经处理完毕,退出循环
    }

	return balancedTernary;
}

int main()
{
	double decimal;
	cout<<"请输入十进制浮点数,将转换成平衡三进制:"<<endl;
	cin >> decimal;
	deque<char> balancedTernary = decimalToBalancedTernary(decimal);
	showDequeArray(balancedTernary);
	return 0;
}

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

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

相关文章

meshlab: pymeshlab合并多个物体模型并保存(flatten visible layers)

一、关于环境 请参考&#xff1a;pymeshlab遍历文件夹中模型、缩放并导出指定格式-CSDN博客 二、关于代码 本文所给出代码仅为参考&#xff0c;禁止转载和引用&#xff0c;仅供个人学习。 本文所给出的例子是https://download.csdn.net/download/weixin_42605076/89233917中的…

【微记录】dmidecode是干什么的?常用来做什么?如何查看系统支持的PCIe版本号(本质:标准,Desktop Management Interface)

是什么 dmidecode 是一个在 Linux 系统提取硬件信息的命令行工具。DMI 代表桌面管理接口&#xff08;Desktop Management Interface&#xff09;&#xff0c;是一种标准&#xff0c;收集桌面计算机的硬件信息&#xff0c;包括系统制造商、序列号、BIOS 信息、系统资产标签等。…

风电功率预测 | 基于PSO-BP神经网络实现风电功率预测(附matlab完整源码)

风电功率预测 风电功率预测完整代码风电功率预测 基于粒子群优化算法(Particle Swarm Optimization, PSO)的BP神经网络是一种常见的方法,用于实现风电功率预测。下面是一个基于PSO-BP神经网络实现风电功率预测的一般步骤: 数据准备:收集与风电场发电功率相关的数据,包括…

C语言----斐波那契数列(附源代码)

各位看官们好&#xff0c;当我写了上一篇博客杨辉三角后&#xff0c;有一些看官叫我讲一下斐波那契数列。对于这个大家应该是有了解的。最简单的规律就是f(n)f(n-2)f(n-1)。就是当前是前两项之和&#xff0c;然后下标1和0都是1.从第三项开始计算的。那么我们知道规律&#xff0…

旧衣服回收小程序:探索旧衣回收市场的创新发展

每年我国就有将近800万吨旧衣服&#xff0c;在生活水平的日益提高下&#xff0c;这个数字也在逐渐增加。目前&#xff0c;我国旧衣回收的产业链也在完善中&#xff0c;旧衣服出口贸易逐年增加&#xff0c;市场发展空间不断扩大。此外&#xff0c;旧衣回收市场投入低、风险小、利…

SystemC学习使用记录

一、概述 对于复杂的片上系统&#xff0c;在进行RTL编码前&#xff0c;需进行深入的系统级仿真&#xff0c;以确认设计的体系结构是否恰当、总线是否能满足吞吐量和实现性要求以及存储器是否浪费&#xff0c;所进行的这些仿真要求在芯片的仿真模型上运行大量的软件&#xff0c…

PLL-分频器

概念 分频器的性能一般用四个参数来规定:(1)分频比&#xff0c;(2)最大允许输入频率fmax&#xff0c;(3)功耗&#xff0c;(4)最小允许输入电压摆幅(也叫“灵敏度”)。虽然分频器的相位噪声也很重要&#xff0c;但在大多数情况下它可以忽略不计。 把一般分频器的输入灵敏度画成…

微信支付商户的“商家转账到零钱”产品快速开通指南

微信支付商户的“商家转账到零钱”功能为商家提供了便捷的转账途径&#xff0c;尤其适用于费用报销、员工福利发放、合作伙伴货款或分销返佣等多种场景。那么&#xff0c;如何快速开通这一功能呢&#xff0c;需要快速开通的商户可以联系小编。 首先&#xff0c;确保你的企业已经…

C++基础与深度解析 | 表达式 | 操作符

文章目录 一、表达式基础1.表达式的值类别2.表达式的类型转换 二、表达式详述1.算术操作符2.逻辑与关系操作符3.位操作符4.赋值操作符5.自增与自减运算符6.其他操作符三、C17对表达式的求值顺序的限定 一、表达式基础 表达式由一到多个操作数组成&#xff0c;可以求值并 ( 通常…

Node.js 学习笔记 express框架

express express 使用express下载express 初体验 express 路由什么是路由1路由的使用验证的方法 2获取请求报文参数3获取路由参数4响应设置响应报文 express 中间件5中间件全局中间件路由中间件 6静态资源中间件注意事项案例 7请求体数据8防盗链实现防盗链 9路由模块化router E…

Linux: Make工具以及Makefile文件

make工具 人们通常利用 make 工具来自动完成编译工作。这些工作包括&#xff1a;如果仅修改了某几个源文件&#xff0c;则只重新编译这几个源文件&#xff1b;如果某个头文件被修改了&#xff0c;则重新编译所有包含该头文件的源文件。利用这种自动编译可大大简化开发工作&…

TreeMap详解:Java 有序 Map 原理与实现

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

论文解读:Self-Prompt Mechanism for Few-Shot Image Recognition

文章汇总 存在的问题 由于提示文本和图像特征之间固有的模态差异&#xff0c;常规的提示方法的性能受到限制。 动机 让视觉信息自己给自己提示 解决办法 SPM涉及到图像编码器跨空间和通道维度产生的固有语义特征的系统选择&#xff0c;从而产生自提示信息。随后&#xff…

【yolov8分类任务-全流程】【公开数据白内障-101:101例白内障手术的视频数据集】

文章目录 1.公开数据集1.1.白内障-101&#xff1a;数据集文件结构1.1.1.视频文件1.1.2.注释文件(1)videos.csv(2) phases.csv(3)annotations.csv 1.2. 数据处理1.2.1.抽帧脚本全部代码&#xff08;每行都有注释&#xff09;1.2.2.分类任务划分数据集脚本 2.yolov8分类任务训练2…

【教程】Jetson安装PyQt5和CUDA版OpenCV

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;请不吝给个[点赞、收藏、关注]哦~ 安装PyQt5 注意目前似乎只支持Python3.6&#xff01;&#xff01;&#xff01; sudo apt install pyqt5* -y sudo apt-get install python3-pyqt…

Java | Leetcode Java题解之第89题格雷编码

题目&#xff1a; 题解&#xff1a; class Solution {public List<Integer> grayCode(int n) {List<Integer> ret new ArrayList<Integer>();for (int i 0; i < 1 << n; i) {ret.add((i >> 1) ^ i);}return ret;} }

每日一题12:Pandas:数据重塑-融合

一、每日一题 解答&#xff1a; import pandas as pddef meltTable(report: pd.DataFrame) -> pd.DataFrame:reshaped_report report.melt(id_varsproduct, var_namequarter, value_namesales)return reshaped_report 题源&#xff1a;Leetcode 二、总结 melt()函数是Pa…

Python 机器学习 基础 之 监督学习 [线性模型] 算法 的简单说明

Python 机器学习 基础 之 监督学习 [线性模型] 算法 的简单说明 目录 Python 机器学习 基础 之 监督学习 [线性模型] 算法 的简单说明 一、简单介绍 二、监督学习 算法 说明前的 数据集 说明 三、监督学习 之 线性模型 算法 1、用于回归的线性模型 2、线性回归&#xff0…

SpringCloud------Feign,Geteway

Feign 所以我们使用一门新的技术&#xff1a;声明式的http客户端Feign 第一步&#xff1a;引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency> …

Vue 封装axios

【一】准备工作 &#xff08;1&#xff09;安装必要插件 安装Axios&#xff0c;这是必要的。默认最新版 npm install axios -S 或 cnpm install axios -S安装elementui-plus&#xff0c;用于提示信息 npm install element-plus --save # 或 cnpm install element-plus --s…