这篇笔记咱主要写一下二进制、八进制、十进制、十六进制之间的互相转换。
通过观察,我觉得二、八、十、十六进制数的互相转换可以总结为三大块:
话不多说,下面就按这三大块来归纳一下。
? 方法:除以基数倒取余
比如16进制,除以的基数就是16
“除以基数”指的是将十进制数不断除以目标进制对应的基数,直到商为0为止。
“倒取余”指的是将每次相除得到的余数倒序排列,即转换为了目标进制的数。
[例] 10进制转换为8进制

图中的红色箭头展示了“倒取余”的过程
图中将十进制数1145转换为了八进制数2171
[例] 10进制转换为16进制

图中的红色箭头展示了“倒取余”的过程
图中将十进制数14191转换为了十六进制数376F
⚠ 不是所有的小数都能转换为其他进制。比如现代计算机采用二进制计数,有很多小数都没法准确地转换为二进制(只能取近似值),这也是为什么说现在计算机无法完全准确地表示小数。
? 方法:乘以基数顺取整
比如2进制,对应的基数就是2
“乘以基数”指的是不断将小数部分乘以目标进制对应的基数,直到小数部分为0为止。
“顺取整”指的是将每次相乘得到的数的整数部分顺序排列,即转换为了目标进制的数。
[例] 2进制转换为10进制

图中的红色箭头展示了“顺取整”的过程
图中将十进制数0.375转换为了二进制数0.011
? 方法:每一位数字乘上基数^对应指数(位权),然后相加求和

本图中的数值
12C.1415926,是十六进制数。
上图中,基数是16,“对应指数”就是橙色标出的数。以小数点为分界,小数点左侧第一位的对应指数为0,而小数点右侧第一位的对应指数为-1。
从低位向高位(图中从右向左),这个指数不断增大。
十六进制的基数是16,那么八进制的基数就是8,以此类推。
[例] 16进制转换为10进制

图中将十六进制数12C.14转换为了十进制数300.078125
二进制和其他进制的互相转换就要方便多了。
? 方法:以小数点为界,向左右两侧,每几位读为一个数,不足的就补零。
关于这里的“每几位”,需要看要转换为哪个进制的数。比如转换为十六进制,其一位能表示0-F这16种状态,需要用4个二进制位来表示,那么就是每4位一读。
再比如八进制一位能表示
0-7这8种状态,需要用3个二进制位来表示,那么就是每3位一读。
关于补零,无论是从小数点左侧第一位开始往左每几位一读,还是从小数点右侧第一位开始往右每几位一读,都难免遇到“位数不够读”的情况,这个时候就需要补零。
[例] 二进制转换为十六进制

图中将二进制数1001001.011转换为了十六进制数49.6
100和011都不足4位,按照读取方向,分别在其左方和右方补零。[例] 二进制转换为八进制

图中将二进制数1001101.1011转换为了八进制数115.54
? 方法:每位读为几位二进制数。
关于这里的“每位读为几位二进制数”,需要看转换前是哪个进制的数。比如原本是十六进制,其一位能表示0-15这16种状态,需要用4个二进制位来表示,那么就是每位读为4位二进制数。
附一个对照表:
| 八进制位 | ←对应的二进制 | 十六进制位 | ←对应的二进制 |
|---|---|---|---|
0 |
000 |
0 |
0000 |
1 |
001 |
1 |
0001 |
2 |
010 |
2 |
0010 |
3 |
011 |
3 |
0011 |
4 |
100 |
4 |
0100 |
5 |
101 |
5 |
0101 |
6 |
110 |
6 |
0110 |
7 |
111 |
7 |
0111 |
| - | - | 8 |
1000 |
| - | - | 9 |
1001 |
| - | - | A |
1010 |
| - | - | B |
1011 |
| - | - | C |
1100 |
| - | - | D |
1101 |
| - | - | E |
1110 |
| - | - | F |
1111 |
实际应用中,可以根据8421码来进行计算,不用死记硬背。
比如三位二进制
101, 对应421,转换为十进制就是4+1=5。
再比如四位二进制1010, 对应8421,转换为十进制就是8+2=10。
[例] 八进制转换为二进制

图中将八进制数67.23转换为了二进制数110111.010011
不想用8421码其实也没问题,八进制和十六进制的每一位数其实可以看作是十进制整数,使用除2倒取余的方法能将其逐位展开为二进制数。
(本质上还是按位读取,每位读为几位二进制数)

比如上图中,原八进制数中的
6与3分别可以用除2倒取余的方法展开为110与011,和8421码得出的结果一致。
十六进制和八进制之间无法直接转换:
通过二进制进行间接转换

上图中我将八进制数12.450先转换为了二进制数001010.100101000,再转换为了十六进制数A.94。
二进制和其他进制互相转换的方法在上面已经介绍过了,这里就不多赘述。
通过十进制进行间接转换

上图中我将八进制数12.450先转换为了十进制数10.578125,再转换为了十六进制数A.94。
十进制和其他进制互相转换的方法在上面也已经介绍过了,这里就不多赘述。
通过二进制进行间接转换

上图中我将十六进制数C.98先转换为了二进制数1100.10011000, 再转换为了八进制数14.46。
可以看到,十六进制转八进制和八进制转十六进制的过程是十分类似的。
通过十进制进行间接转换

上图中我将十六进制数C.98先转换为了十进制数12.59375, 再转换为了八进制数14.46。

这位老伙计为什么要在万圣节前夜穿上圣诞节的服装呢?
答:因为 Oct 31 = Dec 25。
October(十月) 31 是万圣节前夜,December(十二月) 25 是圣诞节。
但是在这也可以理解成Octal(八进制)31= Decimal(十进制)25(*^_^*)
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi
问题1:我无法通过以下方式找到将负整数转换为二进制的方法。我应该像这样转换它。-3=>"11111111111111111111111111111101"我在下面试过:sprintf('%b',-3)=>"..101"#..appearsanddoesnotshow111111bit.-3.to_s(2)=>"-11"#Thisjustadds-tothebinaryofthepositiveinteger3.问题2:有趣的是,如果我使用在线转换器,它告诉我-3的二进制是“0010110100110011”。"11111111111111111111111111111101"和"001
给定一个元素和一个数组,Ruby#index方法返回元素在数组中的位置。我使用二进制搜索实现了我自己的索引方法,期望我的方法会优于内置方法。令我惊讶的是,内置的在实验中的运行速度大约是我的三倍。有Rubyist知道原因吗? 最佳答案 内置#indexisnotabinarysearch,这只是一个简单的迭代搜索。但是,它是用C而不是Ruby实现的,因此自然可以快几个数量级。 关于Ruby#index方法VS二进制搜索,我们在StackOverflow上找到一个类似的问题:
我知道我可以使用Fixnum#to_s将整数表示为二进制格式的字符串。但是1.to_s(2)生成1而我希望它生成00000001。我怎样才能使所有返回的字符串都以零作为填充到8个字符?我可以使用类似的东西:binary="#{'0'*(8-(1.to_s(2)).size)}#{1.to_s(2)}"if(1.to_s(2)).size但这看起来不是很优雅。 最佳答案 使用字符串格式。"%08b"%1#=>"00000001" 关于ruby-如何在Ruby中返回整数的固定长度二进制表示?
我正在尝试使用Ruby将二进制文件转换为十六进制。目前我有以下内容:File.open(out_name,'w')do|f|f.puts"constunsignedintmodFileSize=#{data.length};"f.puts"constcharmodFile[]={"first_line=truedata.bytes.each_slice(15)do|a|line=a.map{|b|",#{b}"}.joiniffirst_linef.putsline[1..-1]elsef.putslineendfirst_line=falseendf.puts"};"end这是以下代
我有一个类似C的结构:SomeStruct:lenVarsstring:namestring:lname#...end我在:Person之前有一堆偏移量和长度。所有偏移量和长度都描述了:Person结构中的数据。如何从指定的偏移量、给定的长度或直到下一个偏移量开始读取数据? 最佳答案 寻求偏移1234,然后将32个字节读入Strings:open'some-binary-file','r'do|f|f.seek1234s=f.read32#thoinyourcase,somethinglike:o=aBinData_object.r
如何在ruby中将十六进制字符串转换为32位有符号整数?例如a="fb6d8cf1"#hexstring[a].pack('H*').unpack('l')#fromthedocumentationitunpackstoits32bitsignedint它转换为-242455045但实际答案是-76706575你能指出我做错了什么吗? 最佳答案 您似乎遇到了字节序问题。这给出了期望的结果:[a].pack("H*").unpack("l>")#=>[-76706575]["038a67f90"].pack("H*").unpac
如果我运行以下代码,前两行会返回我所期望的结果。然而,第三个返回2的二进制表示。2.to_s#=>"2"2.to_s*2#=>"22"2.to_s*2#=>"10"我知道在调用to_s时传入2会将我的输出转换为二进制,但为什么to_s忽略第三个中的*案件?如果有任何不同,我正在运行Ruby1.9.2。 最佳答案 对,正如Namida已经提到的,Ruby解释2.to_s*2作为2.to_s(*2)因为方法调用中的圆括号在Ruby中是可选的。这里的星号就是所谓的splatoperator.这里唯一令人费解的问题是为什么*2的计算结果为2
我正在用Ruby编写一个6502汇编器。我正在寻找一种方法来验证字符串形式的十六进制操作数。我知道String对象提供了一个“十六进制”方法来返回一个数字,但是我遇到了一个问题:"0A".hex#=>10-avalidhexadecimalvalue"0Z".hex#=>0-invalid,producesazero"asfd".hex#=>10-Why10?Iguessitreads'a'firstandstopsat's'?输入一堆乱码会得到一些奇怪的结果。我需要的是一种方法来首先验证该值是合法的十六进制字符串。我在玩正则表达式,并意识到我可以做到这一点:trueif"0A"=~/