我和我的同事一直在思考,以找出为什么有人会以除10为底的底数来编程数字。
我建议您也许可以通过将变量放置在要使用的正确基数中来优化较长的方程(例如,如果您只有5组东西而没有余数,则可以使用5基数),但是我不确定如果是真的。
有什么想法吗?
我和我的同事一直在思考,以找出为什么有人会以除10为底的底数来编程数字。
我建议您也许可以通过将变量放置在要使用的正确基数中来优化较长的方程(例如,如果您只有5组东西而没有余数,则可以使用5基数),但是我不确定如果是真的。
有什么想法吗?
Answers:
除了以10为基数以外,用代码写数字的通常原因是因为您有点纠结。
举一个C语言的例子(因为C语言对任何事物都有利,它对位纠缠也很有用),说一些低级格式在一个字节中编码一个2位和一个6位数字xx yyyyyy
:
main() {
unsigned char codevalue = 0x94; // 10 010100
printf("x=%d, y=%d\n", (codevalue & 0xc0) >> 6, (codevalue & 0x3f));
}
产生
x=2, y=20
在这种情况下,用十六进制写常数要比用十进制写常数要容易些,因为一个十六进制数字整齐地对应于四个位(半字节;一个“半字节”)和两个对应于一个字节:该数字0x3f
包含所有位在低半字节中设置,在高半字节中设置两位。
您也可以用八进制写第二行:
printf("x=%d, y=%d\n", (codevalue & 0300) >> 6, (codevalue & 077));
这里,每个数字对应于一个三比特的块。有些人觉得更容易思考,尽管我认为这几天很少见。
我使用不同基准的主要原因是当我关心位时。
它更容易阅读
int mask=0xFF;
byte bottom_byte = value & mask;
比
int mask=255;
byte bottom_byte = value & mask;
或更复杂的图像
int mask=0xFF00FF00;
int top_bytes_by_word = value & mask;
相比
int mask=4278255360; //can you say magic number!?
int top_bytes_by_word = value & mask;
在此非常清楚十六进制示例的用意是什么,因为十六进制基本上只是二进制的一种更紧凑的形式...相比之下,base-10(我们使用的)与二进制的映射关系不佳。
0xFF = b11111111 = 255
0xFFFF = b1111111111111111 = 65536
0xF0F0 = b1111000011110000 = 61680
您还可以使用某些语言使用其他基础。除了二进制,十六进制和十进制之外,您几乎没有使用其他基数。一些奇数的人仍然使用八进制,但这是在理智的程序中看到的最深奥的东西。
您可能知道,计算机基于二进制文件-这是基于2的。
在基数2和4、8和16(以及2的倍数)之间进行转换很容易,并且将这种转换保留在源代码中可以使处理数字变得更加容易。
对于汇编语言和C语言之类的低级语言,这可以直接转换为处理器操作(例如,用于除法和乘法的位移位),这意味着使用这些数字基最终会产生更快的代码。
此外,并非所有运算都是数字运算-您确实需要在位图上直接摆弄这些位图-使用以2为底的整数或整数倍可以简化运算。
如果您想了解更多信息,建议阅读Charles Petzold的Code。
除了高度专业化的程序外,很少使用10、16或2以外的基数。
基数16(十六进制)非常有用,因为字节的整个范围(0-255)可以用两位数字(0x00-0xFF)表示,这可以使原始十六进制转储或二进制数据的使用变得更加容易。当使用带位运算符的位掩码时,十六进制也很有用,因为与字节对应的两位数字有助于提高可读性。
极少数情况下,基数2(二进制)也可以与按位运算一起使用,但是许多编程语言不支持基数2的文字,而且十六进制反而更加简洁易读。
由于UNIX文件许可权,有时也使用Base-8(八进制)。除此之外,在高度专业化的数学环境之外使用除10以外的基数是非常罕见的。
使用其他基数的最常见的正当理由与转换为基数2的难易程度有关:将基数为8或基数为16的数字转换为二进制数而无需使用计算器,只需记住8或16的简短表就很容易了数字:
0000 0 0001 1 0010 2 0011 3
0100 4 0101 5 0110 6 0111 7
1000 8 1001 9 1010 A 1011 B
1100 C 1101 D 1110 E 1111 F
这带来了多种可能性:
0xFF00FF
是品红(红+蓝); 当你出现时,任务要困难得多16711935
计算机(或更准确地说是编译器)实际上根本不在乎您在源代码中使用的数字基数。最常用的编程语言直接支持基数8(八进制),10(十进制)和16(十六进制)。有些还直接支持基数2(二进制)的数字。专门的语言也可能支持其他数字基础。(通过“直接支持”,我的意思是它们允许在该基数中输入数字,而无需在源代码本身中诉诸数学技巧,例如移位,乘法,除法等。例如,C直接以其支持基数16。0x
数字前缀和常规十六进制数字集0123456789ABCDEF。现在,这些技巧可能有助于使数字更易于理解,但是只要您在没有数字的情况下也可以表达相同的数字,这样做(或不这样做)只是一种方便。)
最后,这是无关紧要的。假设您有如下声明:
int n = 10;
目的是创建一个整数变量,并使用十进制数字10对其进行初始化。计算机会看到什么?
i n t n = 1 0 ;
69 6e 74 20 6e 20 3d 20 31 30 3b (ASCII, hex)
编译器将对此进行标记化,并意识到您正在int
使用name 声明类型的变量n
,并为其分配一些初始值。但是那个值是多少?
对于计算机而言,忽略字节顺序和对齐问题,该变量的初始值输入为0x31 0x30
。这是否意味着初始值为0x3130(以10为底的12592)?当然不是。语言解析器必须继续使用所使用的字符编码来读取文件,因此它先读取1
0
后跟语句终止符。由于假定使用该语言的基数为10,因此(向后)读为“ 0个,1个十进制,结尾”。即,值为十进制。
如果我们以十六进制指定一个值,并且我们的语言用于0x
指定以下值以十六进制表示,那么我们将得到以下内容:
i n t n = 0 x 1 0 ;
69 6e 74 20 6e 20 3d 20 30 78 31 30 3b (ASCII, hex)
编译器将看到0x
(0x30 0x78)并将其识别为以16为底的前缀,因此将在其后寻找有效的以16为底的数字。直到语句终止符为为止10
。这将转换为0“ 1”,1“ 16”,在基数10中等于16。或者在基数2中等于00010000。或者,您也可以代表它。
在这两种情况下,为了简单起见,编译器都忽略了优化,它分配了足够的存储空间来保存int
类型变量的值,并将从源代码中读取的值放置到某种临时的保存变量中。然后(可能要晚得多)将结果二进制值写入目标代码文件。
如您所见,在源代码中编写数值的方式完全无关紧要。它可能对编译时间有很小的影响,但我可以想象(再次忽略操作系统的磁盘缓存之类的优化)诸如磁盘旋转盘周围的随机湍流,磁盘访问时间,数据总线冲突之类的事情。等等,效果要大得多。
底线:不用担心。在您选择的编程语言支持的基础上写数字,这对于如何使用和/或读取数字很有意义。您花了更多的时间来阅读此答案,这比通过巧妙地在源代码中使用哪个数字基数来节省编译时间要多得多。;)
为什么有人会用除10以外的底数来编程数字
以下是一些尚未出现的原因...
x00-某些操作系统和硬件设备的API期望参数为十六进制/二进制。当您为此类API编写代码时,使用数字与API期望的格式相同的数字更容易,而不是在不同的基数之间进行转换。例如,将消息字节的结尾发送到服务器或发送消息以关闭与通信通道的连接。
x01-您可能希望您的应用程序代表某些键盘上不可用的字符,例如版权符号(\ u00a9)。
x02-在不同的区域性设置中(在视觉上)保留一些常量/文字,特别是当源代码/文件在具有不同本地设置的开发人员之间移动时。
x03-使他们的代码看起来混乱和复杂-好是C#不支持八进制常量!
关键问题在于以合理的方式表示单个计算机大小。6502是8位处理器。4004是4位处理器。
当处理4或8位数字时,效果很好。4位数字是单个十六进制字符。8位数字(一个字节)是两个十六进制数字。具有2字大小幂的系统是当今常见的标准-16位,32位,64位。所有这些都很好地除以4以表示为十六进制。
八进制(基数8)用于单词大小为12、24或36的系统中。PDP8,IBM Mainframe和ICL 1900早已使用。使用八位字节而不是有限范围的十六进制更容易表示这些单词(是的,它们也分为4个)。
显然,使用基数为8的编号还可以节省成本。代表BCD中的12位,第一个数字只能是0-4,但是第二,第三和第四位可以是0-9。如果将其设置为十六进制,则一个具有3个十六进制字符,但是每个十六进制字符。生产仅具有0-7 的数码管比具有0-9(对于BCD具有附加逻辑)或十六进制的0-F 的数码管便宜。
今天仍然可以看到八进制的unix文件权限(755、644),其中所有者,组和世界每个都有3位代表权限。
在数学世界中,偶尔会用不同的基础做一些奇怪的事情。例如,来自euler计划396的较弱的Goodstein序列...或更简单的回文数。以N为底的数字具有一个属性,即N-1的倍数的数字总和为N-1的倍数。此外,如果N-1是一个完美的正方形,则sqrt(N-1)也存在此属性。这在某些数学问题中有一些应用。
经常使用基数为16(十六进制)的数字的一个区域是指定颜色,尤其是在Web上使用HTML / CSS时。我们在数字显示器上使用的颜色是通过将3种“基本”颜色(RGB-红色,绿色,蓝色)的3个强度值组合在一起来指定的,这些颜色混合在一起以创建1600万种可显示颜色中的任何一种(使用24位颜色) )。
例如,十六进制的全强度绿色将是0x00ff00
和65280
十进制。现在,想象一下尝试“手动”混合您的头部中具有相等的红色和蓝色(例如强度为一半)的颜色以创建漂亮的紫色:)用十六进制表示,就像0x800080
用十进制值表示那样8388736
。使用灰色阴影时,它变得更加容易-50%的灰度是0x808080
(十六进制)和8421504
(十进制),75%的灰度是0xC0C0C0
和12632256
,依此类推。
使用十六进制要直观得多,只要熟悉十六进制值,任何人都可以立即“猜测”该颜色。如果您需要多次使用相同的颜色(通常是这种情况),那么也容易出错。
检出任何网页(尤其是CSS)以获取疯狂的十六进制用法:D
注意:在CSS中,十六进制值是使用#
前缀写的,例如:#00ff00
绿色,有时也缩短为三位数,例如#0f0
绿色。
对于某些算法,以2为底的意义比其他任何意义都重要。例如,您是否愿意编写一个遍历二叉树或十进制树的函数?
但是,更经常使用基数2,因为这是计算机几乎通用地表示其数字的方式。这意味着:
此外,总有一种罕见的应用程序固有地需要一个奇数基,该奇数基既不能是2也不是10。
2
您正在使用什么奇怪的字符?
老实说,这是偏爱,如果您出于某种原因拥有多指并且有11根手指,或者喜欢用脚趾数数,因此您喜欢以20为基数工作,那完全取决于您。但是要意识到,在一个普遍性主题上,如果我们得到一些在基数19中进行位操作的东西,那么我们大多数每天必须处理比特和字节的人就会被打勾。
BASE X的原因
以10为基数-所有事物的模型,因为我们有10个计数数字(脚既怪异又臭,所以我们不使用这些数字)。
基数2-计算机将其用于位(开/关),这与栅极/晶体管/电容器所传播的可读电压电平有关。
Base 8-旧的,当计算机不是超级庞大时(或当它们在空间方面明智时),这对某些东西或其他东西(我一点都不喜欢)有好处
Base 16-适合显示字节的上下半字节以进行位操作。这在嵌入式/ fpga /硬件世界中超级有用。
计算机中的正常基础
顺带一提,我可以确切地告诉您颜色在十六进制RGB值中的“开启”程度,因此可以在硬件中以单个int表示,然后可以将某些偏移返回给我轻松实现1种复杂的颜色= 1个数据点,非常适合内存有限的大型图像处理。将其与以10为基数的表示形式进行比较,可以将它们全部相加并存储在一个数字中,但是哪个数字是哪个数字,或者R是时间10000,G是100,B是它自己的空间,那么这是很多数学运算,乘法通常要花费比移位更多的周期,因此下一个数据片段已经在队列中,而最后一个数据片段正在处理之前,哎呀,现在不见了。
有时,最好以2、8或16为基数工作。在大多数机器中,乘以2只是一点点移位,而这些机器却超快,除以2。
进一步阐述一下位旋转的想法。在嵌入式环境中工作时,需要访问很多灯,开关或其他寄存器映射项的数组很多次。
在这种情况下,为每个开关分配整个char,byte或int既低效又愚蠢,一个开关或灯有2个位置-接通和断开-为什么我要分配最多256个位置或2 ^ 16的东西阵列中的每个灯都可以是1位,将8个或16个或32个或64个或128个(数据类型的宽度)适合在单个字/寄存器上。需要空间效率,这是值得欢迎的。
在编程中使用以2 ^ n为基数的东西来处理诸如RGB数据,大量信号数据(GPS,音频,ASCII等)之类的十六进制,二进制和八进制要简单得多,因为这就是在机器中的表示方式,并且可以更容易辨别正在呈现的内容以及如何对其进行操作。
使用奇怪的基地
除非您对此进行编码,否则没有效率。您希望以11为基数,必须为其设置数据类型,并使任何运算符重载以向用户处理其表示形式。我认为没有理由将拥有5个项目并且仅拥有5个项目的倍数的系统转换为5个项目数学。此外,您最好祈祷谁决定为基础271编写代码的人对其进行了很好的记录,或者您可以花更多的时间来理解它而不是创建基础271值得,因为所有项目都是271的倍数。
早在计算机时代,我们就有许多显示器可以显示数字0-9,但是我们还没有AF。
http://ad7zj.net/kd7lmo/images/ground_nixie_front.jpg就是这样的一个例子...
八进制非常适合这些显示,并且比二进制或十进制容易。
令我惊讶的是,所有其他答案都没有提到在计算备用基数时有两种非常常见的用法:
压缩:通常希望以较大的基数表示二进制,十进制或十六进制数,以缩短表示形式。例如,像bit.ly这样的所有缩短器都在执行此操作。或者,您可以这样做以缩短在URL中使用的GUID。
- 821F6321-881B-4492-8F84-942186DF059B (base-16 guid)
becomes
- RRIDHW463YD8YXX7MIDI (base-36)
- 3UFmaWDjj9lifYyuT0 (base-62)