mybatis字符串转成数字_计算机储存数字和字符的方法你了解多少?

前语:不要为了读文章而读文章,一定要带着问题来读文章,勤思考。

6a11eaf9ee4de295995d6547bc6506ed.png本文链接: http://1t.click/J7E

前言

最近在学习中涉及到计算机储存、传输数字和字符等操作,由于对字节、2进制、10进制、16进制、ASCII码的概念以及它们之间的关系和转换理解的不够透彻,导致在通讯、MD5消息摘要算法等时候出现问题,是因为数据转成计算机认识的01的这个环节出现问题。由于这个问题并不是那么容易发现,所以我也算是花了挺多时间才解决了这个问题,记录下解决过程,顺便也当复习一下计算机组成原理。

ASCII码

在计算机中,所有的数据在存储和运算时都要使用二进制数表示(因为计算机用高电平和低电平分别表示1和0),例如,像a、b、c、d这样的52个字母(包括大写)以及0、1等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,当然每个人都可以约定自己的一套(这就叫编码),而大家如果要想互相通信而不造成混乱,那么大家就必须使用相同的编码规则,于是美国有关的标准化组织就出台了ASCII编码,统一规定了上述常用符号用哪些二进制数来表示。ASCII 码一共规定了128个字符(0000 0000-0111 1111)的编码,比如空格SPACE是32(二进制0010 0000),大写的字母A是65(二进制0100 0001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位(低7位),最前面的一位(高1位)统一规定为0(不要和数字的符号位搞混)。当然除了ASCII码,还有UTF-8、GBK等。字节字节(Byte)普通计算机系统能读取和定位到最小信息单位,即我们通过计算机储存和传输数据的时候都是先把数据转成字节。字节即Byte,一个字节代表8个比特(Bit),字节通常缩写为B,比特通常缩写为b。字节的大小是8Bit,即字节的范围是0000 00001111 1111,对于无符号型,它表示的十进制范围是[0,255],对于有符号型,高一位表示符号位,它表示的十进制范围是[-128,127]。

计算机如何储存数据

计算机只认识01(因为计算机只有高低电平两个状态),数据要想通过计算机储存或者传输,首先是要把数据转成计算机能认识的格式即01数据。我们举个例子,以储存十进制数字28-28为例,首先将十进制数转成二进制。
需要注意的是: 数字在计算机中储存的是补码,而字符是在计算机中储存的是字符对应的编码(不要和数字的补码搞混)。

数字

储存十进制数字28-28为例,首先将十进制数转成二进制,高1位为0代表正数,为1代表负数
12
28(10) = 0001 1100(2)(原码)-28(10) = 1001 1100(2)(原码)
然后计算机将二进制数字进行补码运算,运算结果如下
12
28(10) = 0001 1100(2)(原码) =  0001 1100(2)(补码)-28(10) = 1001 1100(2)(原码) = 1110 0100(2)(补码)

然后计算机保存的就是补码,当要取出数据的时候,就将补码逆运算一下,即可求出原码,再将原码转换一下就可以得到真实的数据了。

下面以Java语言演示这个过程,首先我们要清楚Java的byte、short、int、long都是有符号的(signed)
123456789101112131415161718
public class test {    public static void main(String[] args) throws NoSuchAlgorithmException {        int a1 = 28;        int a2 = -28;//        转成二进制表示        String b1 = Integer.toBinaryString(a1);        String b2 = Integer.toBinaryString(a2);//        转成无无符号表示        String b3 = Integer.toUnsignedString(a1);        String b4 = Integer.toUnsignedString(a2);        System.out.println("28储存到计算机后为:" + b1);        System.out.println("-28储存到计算机后为:" + b2);        System.out.println("取出储存的28 以无符号表示:" + b3);        System.out.println("取出储存的-28 以无符号表示:" + b4);    }}
运行输出:
1234
28储存到计算机后为:11100-28储存到计算机后为:11111111111111111111111111100100取出储存的28 以无符号表示:28取出储存的-28 以无符号表示:4294967268
我们验证一下结果,验证了计算机确实是以补码的方式储存数字。这里有个小问题,就是我们知道int型有4个字节即32个比特,但是28却输出了111005个比特而已,是因为toBinaryString()方法把11100前面的0给忽略了。取出的时候,我们以无符号的标准去处理,导致取出存入的-28结果是4294967268和我们存入的不一样,这是因为-28是负数,负数的补码和原码不一样,而用无符号处理的话就是直接将11111111111111111111111111100100转成结果了。而为什么28用有无符号处理结果都一样是因为正数的原码和补码一样,这样验证了Java的数据类型都是有符号的。至于计算机为什么用补码来储存数字,而不是原码,原因是:拿单字节整数来说,无符号型,其表示范围是[0,255],总共表示了256个数据。有符号型,其表示范围是[-128,127]。先看无符号,原码和补码都一样,0表示为0000 0000255表示为1111 1111,刚好满足了要求,可以表示256个数据。再看有符号的,若是用原码表示,0表示为0000 000。因为咱们有符号,所以应该也有个负0(虽然它还是0)1000 0000。这样的话那就有2个0,也就是只能表示255个数据,不能够满足我们的要求。而用补码则很好的解决了这个问题。

字符

在计算机中,对非数值的字符进行处理时,要对字符进行数字化,即用二进制编码来表示字符。其中西文字符最常用到的编码方案有ASCII编码和EBCDIC编码。对于汉字,我国也制定的相应的编码方案,比如 GBK,GB2312等。比如字符aASCII码十进制值为97,在计算机中用二进制表示就是 01100001。下面同样用Java来演示计算机是如何储存字符的。1.采用UTF-8和GBK两种编码储存汉字
12345678910111213141516171819202122
public class test {    public static void main(String[] args) throws NoSuchAlgorithmException {        String a1 = "中";//        采用两种不同的编码储存"中"这个汉字 比较两种编码        byte[] b1 = a1.getBytes("GBK");        byte[] b2 = a1.getBytes("UTF-8");        String c1 = binary(b1,2);        String c2= binary(b2,2);        System.out.println("GBK储存对应的二进制:" + c1);        System.out.println("UTF-8储存对应的二进制:" +c2);    }    /**     * 将byte[]转为各种进制的字符串     * @param bytes byte[]     * @param radix 基数可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制     * @return 转换后的字符串     */    public static String binary(byte[] bytes, int radix){        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数    }}
a4e7f45a83bdad16b72619cd1a0a7173.png我们调试看看,发现GBK编码采用2个字节储存,储存的数据分别是10进制的-42-48对应的二进制分别是1101011011010000(补码),即汉字对应的二进制为1101011011010000,即16进制的D6D0,查看GBK对照表,发现16进制编码D6D0对应的汉字确实是33c38c985cfa14cc501054c72450bbd4.png而UTF-8编码采用3个字节储存,同理将对应的二进制111001001011100010101101转成16进制,为E4B8AD,通过UTF-8编码查询,发现汉字对应的16进制编码确实是E4B8AD110bd345a60312b20f5832e3e10f6cb5.png2.储存字符
12345678910111213141516171819
public class test {    public static void main(String[] args) throws NoSuchAlgorithmException {        String a1 = "EF";//        将字符串转成字节数组        byte[] b1 = a1.getBytes();        String c1 = binary(b1,2);        System.out.println("对应的二进制:" + c1);    }    /**     * 将byte[]转为各种进制的字符串     * @param bytes byte[]     * @param radix 基数可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制     * @return 转换后的字符串     */    public static String binary(byte[] bytes, int radix){        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数    }}
570436363bccfc5238d208118d28ff3c.png调试看看,字符串EFEF两个字符,它们对应的十进制ASCII码分别是697036f02f9d40526c148769e59cecfd3c9c.png我们发现Java的getBytes()方法是将字符串的每一个字符都储存到一个字节的,如果我们想把EF储存在一个字节里面,即EF是一个整体的,一个字节,不能拆分,那我们可以把EF放在一个字节里面(byte)(0xEF),声明它是一个字节,不是字符,不用再将它转成字符对应的编码。下面说说我在进行MD5消息摘要算法时候遇到的坑,我要对QQ号对应的Hex进行MD5算法散列,这里我举例QQ号的10进制为12345678,对应的16进制为00BC614E(因为QQ号固定长度4个字节,所以前面补了2个0),一开始我是以下面的方式进行MD5算法的
12345678910111213141516171819202122232425
public class test {    public static void main(String[] args) throws NoSuchAlgorithmException {        String qq = "00BC614E";//        将字符串转成字节数组        byte[] b1 = qq.getBytes();        MessageDigest md = MessageDigest.getInstance("MD5");        md.update(b1);//        得到MD5后的哈希值        byte[] hash = md.digest();//        将结构转成16进制        String c1 = binary(hash,16);        System.out.println("对应的16进制:" + c1);    }    /**     * 将byte[]转为各种进制的字符串     * @param bytes byte[]     * @param radix 基数可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制     * @return 转换后的字符串     */    public static String binary(byte[] bytes, int radix){        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数    }}
02b9b0de627e11f00026419307384e5b.png调试可以看到上面的代码其实是将字符串00BC614E转成了8个字节,然后再对这8个字节进行散列,这也是基于字符串进行的MD5散列,和通过网上一些网站散列得到的值是一样的c4c2296bb0cfafd2faefdf748d0e18ed.png但是这个哈希值和预想的结果不一致,后来才知道预想的结果是基于字节进行的MD5散列,也就是00BC614E应该分成4个字节(00、BC、61、4E)而不是8个字节(0、0、B、C、6、1、4、E),然后通过修改代码
123456789101112131415161718192021222324252627
public class test {    public static void main(String[] args) throws NoSuchAlgorithmException {//        String qq = "00BC614E";//        将字符串转成字节数组//        byte[] b1 = qq.getBytes();        byte[] b1 = {(byte)(0x00),(byte)(0xBC),(byte)(0x61),(byte)(0x4E)};        MessageDigest md = MessageDigest.getInstance("MD5");        md.update(b1);//        得到MD5后的哈希值        byte[] hash = md.digest();//        将结构转成16进制        String c1 = binary(hash,16);        System.out.println("对应的16进制:" + c1);    }    /**     * 将byte[]转为各种进制的字符串     * @param bytes byte[]     * @param radix 基数可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制     * @return 转换后的字符串     */    public static String binary(byte[] bytes, int radix){        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数    }}
6a2cb3748ddddb80a3785fb9f4e4abc2.png使用(byte)声明是一个字节,不是字符,不用再将它转成字符对应的编码。00、BC、61、4E分别是一个字节,当然因为字节为8个比特,能表示256个数字,因为Java的数据类型是有符号的,所以8个比特能表示的10进制范围是[-128,127],所以(byte)(x) x不能小于-128和不能大于127,否则会溢出,溢出的部分数据会丢失。热文推荐你知道SQL的这些错误用法吗?提高面试通过率?首先要具备以下技能。听说这10道Java面试题90%的人都不会!!!b4bd5f5d62ab77e0943dc3b79a4d4050.png同时,分享一份Java面试资料给大家,覆盖了算法题目、常见面试题、JVM、锁、高并发、反射、Spring原理、微服务、Zookeeper、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 面试 领取。

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

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

相关文章

usb连接不上 艾德克斯电源_艾德克斯HT3150联机和IT6720校准联机记

大概2年前,坛里入了一台设置电压比输出电压高几伏的IT6720电源,到手发现,里面被修得惨不忍睹。到手的时候是110V的,没想到这种型号,跳线要改焊控制变压器和高压部分两个跳线,只修改了控制变压器跳线&#x…

经典兔子问题python视频_Python练习题 007:兔子生兔子

【Python练习题 007】 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?------------------------------------------------------…

android调用python框架_在Java中从Android应用程序执行Python脚本?

我正试图找到一种在Android中从Java代码执行Python脚本的方法。我对这个问题做了一个研究,但我发现的唯一问题是,如何在APK for android(Kivy e.t.c.)中转换python脚本。更具体地说,我有一个包含很多函数的脚本,我想做的是在我的j…

使用java向ftp上传多张图片_ftp免费空间,利用ftp工具定时连接ftp免费空间教程及java配置...

IIS7服务器管理工具这款ftp客户端软件,可以批量管理ftp站点,还可以实现ftp定时上传、定时下载,定时备份、自动更新等功能。关于ftp客户端功能,它主要实现以下四点功能:1、ftp 批量操作2、ftp 定时同步(上传…

mysql fulltext 分页_关于MySQL的FULLTEXT实现全文检索的注意事项

对于英文,MySQL的FULLTEXT属性来实现全文检索是相当方便且高效的,但是在使用过程中需要注意一些事项。首先对我们对需要进行检索的字段添加FULLTEXT属性(假设已经建表):SQL:alter table table_name add fulltext index(filed_1,fi…

损失函数的意义和作用_损失函数的可视化:浅论模型的参数空间与正则

点击蓝字关注我们作者丨土豆知乎来源丨https://zhuanlan.zhihu.com/p/158857128本文已获授权,不得二次转载前言在深度学习中,我们总是不可避免会碰到各种各样的损失函数。通常来说,损失函数都是高维的函数,难以可视化为人类可以分…

postgres 把一个表的值转成另一个表的字段名_用LUT来做一个可动态配置的卷积核...

引言由于卷积核数据在计算过程中保持不变,更新较慢。这样就可以利用LUT来存储权重并同时进行乘法运算。LUT乘法器的实现很早就已经研究过,本论文正是在此基础上,提出了用于实现可配置的卷积实现方法。基于LUT的乘法器不会受到FPGA中DSP资源的…

mysql储存过程把集合并_MySQL 多日志表结果集合拼接存储过程

通常MySQL单天的日志 只记录当天的日志信息,如果需要查看一月内的日志信息需要对每天的日志表结果集合进行拼接,通常用到 union通常MySQL单天的日志 只记录当天的日志信息,如果需要查看一月内的日志信息需要对每天的日志表结果集合进行拼接,通常用到 uni…

split函数python统计英文单词_统计一篇英文文章单词个数,取出出现频次前10的单词(Python实现)...

题目: 用python实现统计一篇英文文章内每个单词的出现频率,并返回出现频率最高的前10个单词及其出现次数。常规解法怎么判定单词?1 不是字母的特殊字符作为分隔符分割字符串 (避免特殊字符的处理不便,全部替换成"")2 正则分割3 遍…

superset mysql数据源配置_superset 性能优化1-已经使用中的superset更改默认数据源sqlite到mysql...

已经使用中的superset更改默认数据源sqlite到mysql1.提取sqlite db(由于当前使用 docker 需要到宿主)docker cp CONTAINER_NAME:/var/lib/superset/superset.db /opt2.数据导出然后使用 navicat 数据库工具打开sqlite文件选择导出向导csv数据保存到一个文件夹3.创建mysql数据库…

对于一个指针可以多次使用delete_【C++札记】new和delete

malloc,free和new,delete区别:a.malloc,free是C/C的标准库函数。new,delete是c的操作符。b.malloc申请的是内存,严格意义不是“对象”,new申请的可以理解为“对象”,new 时会调用构造函数,返回指向该对象的指针。c.对于…

java循环队列_Java 循环队列的实现

队列概念队列(Queue)是限定只能在一端插入、另一端删除的线性表。允许删除的一端叫做队头(front),允许插入的一端叫做队尾(rear),没有元素的队列称为“空队列”。队列具有先进先出(FIFO)的特性。普通顺序队列存在的问题在普通顺序队列中,入队的操作就是先将尾指针re…

python大数据开发平台_python示例

### 结合使用 GET 和 Authorization 标头 (Python)以下示例说明如何使用 [根据方案编号获取内容列表](http://open.gsdata.cn/article/info?id1) API 发出请求。该请求发出 GET 请求,并使用 Authorization 标头将身份验证信息发送到 GSDATA。~~~#!/usr/bin/python#…

java 遍历hashmap key_Java5种遍历HashMap数据的写法

本文介绍了最好的Java5种遍历HashMap数据的写法&#xff0c;分享给大家&#xff0c;也给自己留一个笔记&#xff0c;具体如下&#xff1a;通过EntrySet的迭代器遍历Iterator < Entry < Integer, String >> iterator coursesMap.entrySet().iterator();while (iter…

python不能卸载原因_linux上python卸载不了是什么原因?

linux下卸载python&#xff1a;1.首先查看自己电脑的python版本在root下&#xff0c;python3 --version python3.5.3python --version python 2.7.132.说实话&#xff0c;对于这点我不太喜欢&#xff0c;可能是系统自带的&#xff0c;无自己没事就瞎折腾一下&#xff0c;也就是…

java new 多线程_Java多线程实现(四种方法)

1.继承Thread类&#xff0c;重写run方法(其实Thread类本身也实现了Runnable接口)2.实现Runnable接口&#xff0c;重写run方法3.实现Callable接口&#xff0c;重写call方法(有返回值)4.使用线程池(有返回值)1.继承Thread类&#xff0c;重写run方法每次创建一个新的线程&#xff…

oracle删除唯一索引sql语句_高级SQL之在选择语句中使用更新和删除

点击蓝字关注我吧【本文详细介绍了数据库中在选择语句中使用更新和删除的方法&#xff0c;欢迎读者朋友们阅读、转发和收藏&#xff01;】1 基本概念1.1 SQL UPDATE 语句Update 语句Update 语句用于修改表中的数据。语法&#xff1a;UPDATE 表名称 SET 列名称 新值 WHERE 列名…

java 读 jar外文件_读取Jar包外面的配置文件

比较常用的方法是将properties文件直接打入JAR包中&#xff0c;然后使用Properties类进行读取。有时候也需要读取在JAR外面的配置文件。废话不多说&#xff0c;直接上代码&#xff1a;import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOExc…

python随机生成车牌_Python实现随机生成任意数量车牌号

之前做课设的时候舍友遇到了需要生成500w量级车牌号的问题&#xff0c;于是我便写了一个随机生成车牌号的程序&#xff0c;希望各位采纳。注&#xff1a;Python实现import randomdef chepaihao(len6):char0京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽赣粤青藏川宁琼char…

java 多层异常_Java多层嵌套异常处理的基本流程

异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;错误有时候是可以避免的。异常的对象有两个来源&#xff0c;一是Java运行时环境自动抛出系统生成的异常&#xff0c;而不管你是否愿意捕获和处理&#xff0c;它总要被抛出&#xff01;比如除数为0的异…