关于数字存储和byte[]数组的一些心得

news2024/12/24 0:10:58

前言

最近做项目,发现一些规律,比如数字的存储和字符串的存储,先说数字吧,最常见的整数,就涉及反码和补码,根据这些规则,甚至我们自己也能造一种数据存储结构,比如1个字节8bit,在byte里面就是一半正数一半负数,但是在二进制却是我们不理解的一种方式。计算机存储都是字节存储,字符实际上也是字节,那么byte[]数组在很多时候就很关键,比如grpc算法那一期:grpc Java demo与Springboot改造支持grpc通信_grpc-client-spring-boot-starter-CSDN博客

准备demo

demo解说

比如byte 127表示01111111,byte是8bit,所以有一个符号位,但是负数呢

-128就是10000000,这里转int了,4个字节而byte是一个字节,实际上byte=字节,就是直译的

那么我们把int强转为byte呢

这就涉及数据的存储了,计算机不能运算减法,使用加法做减法,那么负数就需要一种表现形式,即符号位,但是bit2进制存储,并不是我们理解的存储方式,这就涉及反码和补码了,数据以补码的形式存储。

原码、反码、补码

数据都是2进制存储,计算机为了做减法,对每个字节的从左到右第一个bit定义为符号位,为什么从左到右,实际上在看UTF-16的编码设计,就有高位和低位的说法,真难懂,字节byte的第一bit为符号位定义清晰。

原码

原码是使用数据本身的定义存储,即符号位1bit,其他是我们真实的数据,非常符合我们的认知。

正整数二进制原码负整数二进制原码
10000 0001-11000 0001
20000 0010-21000 0010
30000 0011-31000 0011
40000 0100-41000 0100
50000 0101-51000 0101

但是原码有个问题:1+ (-1) ≠ 0,这是不允许的。

反码

既然原码1 + (-1) ≠ 0那么,按位取反,就可以了,表示负数

整数的反码与原码一致,负数的反码是除了符号bit,其余bit位按位取反,毕竟反码就是为负数做加法设计的。但是因为负数是按位取反,所以1+(-1) ≠ 0。

正整数二进制反码负整数二进制反码
10000 0001-11111 1110
20000 0010-21111 1101
30000 0011-31111 1100
40000 0100-41111 1011
50000 0101-51111 1010

补码 

负数除了符号位按位取反后,虽然语义清晰了,但是做加法运算仍然是有问题的:

1+(-1)≠ 0,这就需要补码了

正数的原码、反码、补码一致;负数的补码=反码+1bit

正整数二进制补码负整数二进制补码
10000 0001-11111 1111
20000 0010-21111 1110
30000 0011-31111 1101
40000 0100-41111 1100
50000 0101-51111 1011

 实际上数据就是补码存储的,但是每个字节做加法也有问题

1+(-1) = 1 0000 0000

就是超限了,计算机就把超限的bit位舍弃,来达到1+(-1)=0的计算,所以-1就是1111 1111了,但是对于byte来说-128呢,毕竟0111 1111 = 127,即一个字节,所以-128没有原码,当然也没有反码了,只有补码,毕竟0这个特殊的数据,不存在+0和-0的说法。

-128原码= 1 1000 0000 超限byte了,byte只有8bit,去掉符号位只有7位,即原码最大-127

-128反码= 1 0111 1111  原码没有就没有反码了

-128补码= 1 1000 0000 补码

说说0

-0的原码=1 000 0000

-0的反码=1 111 1111

-0的补码=0 000 0000 = +0

神奇的设计。

byte[]数组

那么byte[]数组呢,奇特的地方是每个byte是-128~127,但是多个字节时只有开始的一个bit是符号位,对于多个字节的整个bit位是遵循补码存储的思路,但是对于单个字节就会出现负数表示255的情况。

可以看到255刚好够一个byte存储,转为byte看看

 -1,相当于-1表示255,128表示-128

相当于考虑符号位和多字节不考虑字节本身符号位的表示规则:

127后是-128,然后依次递增+1,知道255=-1

当然,int转byte[]就涉及高低位顺序了,类似utf-16编码。

上次grpc的算法

grpc Java demo与Springboot改造支持grpc通信_grpc-client-spring-boot-starter-CSDN博客 

package org.springframework.http.converter.protobuf;
 
public class LengthBytesUtils {
    public static byte[] intToBytes(int length, int size) {
        byte[] bytes = new byte[size];
        int temp;
        for (int i = size - 1; i > -1; i--) {
            temp = (int) ((length / (Math.pow(253, (size - 1 - i)))) % 253);
            if (temp > 127) {
                temp = -128 + 1 + temp - 127 + 1;
            }
            bytes[i] = (byte) temp;
        }
        return bytes;
    }
 
    public static int bytesToInt(byte[] bytes) {
        int length = 0;
        int size = bytes.length;
        for (int i = 0; i < size; i++) {
            if (bytes[i] == 0){
                continue;
            }
            if (bytes[i] > 0) {
                length += bytes[i] * Math.pow(253, size-1-i);
            } else {
                length += (127-1 + bytes[i] + 128-1) * Math.pow(253, size-1-i);
            }
        }
        return length;
    }
}

 实际上是剔除了一些byte数据表示,但是grpc把长度从int的4字节提升到5字节,相当于创造了一种正整数 数据类型,实际上可以优化为

    public static byte[] intToBytes2(int length, int size) {
        byte[] bytes = new byte[size];
        int temp;
        for (int i = size - 1; i > -1; i--) {
            temp = (byte) ((length / (Math.pow(253, (size - 1 - i)))) % 253);
            if (temp < 0) {
                temp = 3 + temp;
            }
            bytes[i] = (byte) temp;
        }
        return bytes;
    }

    public static int bytesToInt2(byte[] bytes) {
        int length = 0;
        int size = bytes.length;
        for (int i = 0; i < size; i++) {
            if (bytes[i] == 0) {
                continue;
            }
            if (bytes[i] > 0) {
                length += bytes[i] * Math.pow(253, size - 1 - i);
            } else {
                length += (bytes[i] + 253) * Math.pow(253, size - 1 - i);
            }
        }
        return length;
    }

因为int转byte,符号位生效,byte会认为第一个bit是符号位,但是对int的字节数组的每个字节就不一定了,只有最高位bit是符号位,其他都是数据位

int 4个字节

0 0000000  00000000  00000000 10000000 = int 128 = byte[]{0, 0, 0, -128}

但是byte -128转int还是-128,因为是向上转型,是byte类型一定是int类型,反之则不对。

总结

实际上这次是一些碎碎念,核心还是计算机的原理,计算机因为电气性能只设计有0、1,所以是2进制,存算都是2进制。而且计算机在设计之初只设计了加法,没设计或者设计减法有问题,导致数据相减运算都是加运算,所以需要存储和运算负数,那么就需要定义负数的存储和相加逻辑,就设计了反码和补码来存储负数。

另外一个字节存储能力有限,往往需要很多字节来存储一个内容,那么符号位的定义在总体结构很明晰,但是对于字节数组的单个字节就会存在歧义,造成数据可读性很迷惑,因为符号位的特殊意义。同时,我们可以根据需要自定义数据类型,但是字节数组存储会有读取顺序的高低位问题,类似UTF-16编码的左右读取模式。

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

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

相关文章

bbr 和 inflight 守恒的收敛原理

先看 bbr&#xff0c;以 2 条流 bw 收敛为例&#xff0c;微分方程组如下&#xff1a; { d x d t C ⋅ g ⋅ x g ⋅ x y − x d y d t C ⋅ g ⋅ y g ⋅ y x − y \begin{cases} \dfrac{dx}{dt}C\cdot\dfrac{g\cdot x}{g\cdot xy}-x\\\ \dfrac{dy}{dt}C\cdot\dfrac{g\cdot y…

秋风送爽,夏意未央|VELO Prevail Revo坐垫,一骑绿动起来吧~

夏末秋初&#xff0c;当第一片落叶缓缓飘落&#xff0c;是时候骑上你的自行车&#xff0c;迎接新的季节啦。带上维乐Prevail Revo坐垫&#xff0c;因为它独树一帜地采用EVA与回收咖啡渣精制而成的轻量发泡提升了减震性能&#xff0c;可以让你的每一次骑行都充满意义。    “…

基于DS18B20的温度检测

前言 DS18B20是DALLAS半导体公司生产的单总线数字温度传感器&#xff0c;其输出的是数字信号&#xff0c;具有体积小&#xff0c;功耗低&#xff0c;抗干扰能力强&#xff0c;精度高的特点。 温度范围-55摄氏度至125摄氏度&#xff0c;在-10摄氏度至85摄氏度可以达到不超过 0.5…

Redis进阶(五):集群

1.概念 集群&#xff0c;从广义来讲&#xff1a;只要是多个机器&#xff0c;构成了分布式系统&#xff0c;都可以称为一个集群 狭义的集群&#xff1a;redis提供的集群模式&#xff0c;这个集群模式之下&#xff0c;主要是要解决存储空间不足的问题&#xff08;拓展存储空间&…

分歧时间估计与被子植物的年代-文献精读43

Ad fontes: divergence-time estimation and the age of angiosperms 回归本源&#xff1a;分歧时间估计与被子植物的年代 摘要 准确的分歧时间对于解释和理解谱系演化的背景至关重要。在过去的几十年里&#xff0c;有关冠被子植物推测的分子年龄&#xff08;通常估计为晚侏罗…

Python入门全解析丨Part3-Python的循环语句

(一)while循环的基础应用 一.while的条件 >>>需要是布尔类型&#xff0c;True表示继续循环&#xff0c;False表示循环结束 >>>需要设置循环终止的条件 >>>需要空格缩进 二.while循环使用举例 sum0; i1; while i <100:sumi;i1; print(f&quo…

华阳珠珍娘娘宝圣祖庙文化董事会隆重举办

中国广东省汕头市华阳珠珍宝圣祖庙文化董事会隆重举办海内外两岸护婴女神妈祖回娘家启动仪式&#xff01;风暖日丽的初春天&#xff0c;纷纷鼓乐赛华阳。护婴妙化在此地&#xff0c;莲岛故里起瓣香。这首诗是清代华阳乡人游殷享&#xff0c;时任湖北郧西县知县赞叹赛护婴&#…

VLAN 基本配置

一. 实验拓扑 二. 实验简介 交换机的VLAN端口可以分为Access、Trunk和Hybrid3种类型。Access 端口是交换机上用来直接连接用户终端的端口&#xff0c;它只允许属于该端口的缺省VLAN的帧通过。Access端口发往用户终端的帧一定不带VLAN标签。Trunk端口是交换机上用来连接其他交…

【C语言】十六进制、二进制、字节、位

【C语言】十六进制、二进制、字节、位 文章目录 [TOC](文章目录) 前言一、十六进制、二进制、字节、位二、变量、指针、指针变量三、参考文献总结 前言 使用工具&#xff1a; 1.控制器&#xff1a;STM32F103C8T6 2.仿真器&#xff1a;STLINK 提示&#xff1a;以下是本篇文章正…

修改Apollo的依赖版本包,并制作arm版本的镜像

由于一些安全因素&#xff0c;Apollo组件扫描出一些依赖插件存在安全漏洞&#xff0c;因此要修改部分依赖组件的版本&#xff0c;重新制作镜像&#xff0c;我们来看一下如何实现 1. 修改源码 1.1 拉取源码&#xff0c;并切换到我们需要的分支 # 拉取源码项目 git clone gitgi…

TeamTalk消息服务器(群组相关)

具体的流程如下介绍&#xff0c;后续需要着重研究数据库相关表的结构设计。 群组信令和协议设计 enum GroupCmdID {CID_GROUP_NORMAL_LIST_REQUEST 1025,CID_GROUP_NORMAL_LIST_RESPONSE 1026,CID_GROUP_INFO_REQUEST 1027,CID_GROUP_INFO_RESPONSE 1028,// ...... 暂时省…

pm2 + linux + nginx

pm2 pm2是一个用于管理node项目的工具 前言 有如下两个文件 index.js const express require("express"); const app express(); const port 9999;app.get("/index", (req, res) > {res.json({code:200,msg:"songzx001"}) });app.lis…

openGL笔记之序章

本系列来自 youtube 主播cherno的 openGL系列, b站双语版链接 https://www.bilibili.com/video/BV1Ni4y1o7Au?p1&vd_source0be7021510d651441db0edd576304997 openGL 是一个接口规范&#xff0c;定义了一系列接口&#xff0c;我们可以通过使用这些接口来一定程度的操作GP…

[Meachines] [Easy] Safe BOF+ROP链+.data节区注入BOF+函数跳转BOF+KeePass密码管理器密码破译

信息收集 IP AddressOpening Ports10.10.10.147TCP:22&#xff0c;80&#xff0c;1337 $ nmap -p- 10.10.10.147 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10deb9u6 (protocol 2.0) | ssh-hostkey: | 2048 …

基于django的在线音乐网站设计/基于python的音乐播放系统

Django在线音乐网站设计 摘要&#xff1a;计算机网络如果结合使用信息管理系统&#xff0c;能够提高管理员管理的效率&#xff0c;改善服务质量。优秀的在线音乐网站设计能够更有效管理音乐资讯规范&#xff0c;帮助管理者更加有效管理音乐网站&#xff0c;可以帮助提高克服人工…

【深度剖析】《黑神话:悟空》员工薪资大曝光,你慕了吗?

《黑神话&#xff1a;悟空》引爆市场&#xff0c;员工薪资却成热议焦点&#xff01; 自8月20日解锁以来&#xff0c;《黑神话&#xff1a;悟空》以其国产3A游戏的高品质迅速占领市场&#xff0c;引发全球玩家的热烈讨论。深圳市游科互动科技有限公司开发的这款游戏&#xff0c…

C++20 是 C++ 语言的一次重大更新

C20 是 C 语言的一次重大更新&#xff0c;它引入了许多新特性&#xff0c;旨在提高开发者的生产力和代码的现代化。以下是 C20 的一些关键特性的总结&#xff1a; 模块&#xff08;Modules&#xff09;&#xff1a;C20 引入了模块&#xff0c;这是一种新的编译单元&#xff0c;…

CSS解析:定位和层叠上下文

许多开发人员对定位的理解很粗略&#xff0c;如果不完全了解定位&#xff0c;就很容易给自己挖坑。有时候可能会把错误的元素放在其他元素前面&#xff0c;要解决这个问题却没有那么简单。 一般的布局方法是用各种操作来控制文档流的行为。定位则不同&#xff1a;它将元素彻底…

mysql 不同版本安装不同端口

安装版本为Mysql8.0.11 先解压&#xff0c;解压后&#xff0c;包下创建my.ini文件内容如下&#xff1a; 注意&#xff1a;端口不能给别的mysql一样 [mysqld]# 设置3306端口port3307 # 自定义设置mysql的安装目录&#xff0c;即解压mysql压缩包的目录basedirD:\\rj\\mysql8.0.…

如何将 HEIC 转换为 JPG/PNG

“我刚刚将 iPhone 15 升级到 iOS 18&#xff0c;但新 iPhone 的照片现在变为 HEIC。什么是 HEIC 格式&#xff1f;我可以在 Windows 上使用 HEIC 照片吗&#xff1f;有人知道 HEIC 的技巧吗&#xff1f;谢谢&#xff01;” 当你换了一部新的iPhone时&#xff0c;你会发现你的图…