计算机如何将所有内容转换为二进制?当它们看到一个二进制代码时,它们如何知道它代表一个数字、一个单词还是一条指令?

10
我知道计算机如何将数字转换为二进制。但我不明白的是,我听说计算机将所有内容(单词、指令等)都转换为二进制,而不仅仅是数字。这是怎么做到的呢?
你能给我举些例子吗?比如计算机如何将字母“A”转换成二进制?
当计算机看到一个二进制代码时,它如何知道那一长串0和1代表的是数字、单词还是指令?
例如:
假设计算机程序员将字母“Z”编码为这个二进制字符串:11011001111011010111
当计算机遇到这个二进制字符串时,它会将其翻译成字母“Z”。
但是当我们问这台计算机“709乘以1259的积是多少?”时,它会回答我们“892631”。但是,当这个数字转换成二进制时,它也是11011001111011010111。
那么它如何区分“Z”和“892631”呢?
请注意,我对计算机科学并不了解,请用简单易懂的语言来解释一切。

5个回答

10

计算机实际上并不将任何内容翻译成二进制,从一开始就是二进制,计算机除了二进制什么都不知道。

存储在内存中的字符A将会是01000001,而计算机只把它看作是一个二进制数。当我们要求计算机在屏幕上显示该数字对应的字符时,它会在字体定义中查找其图形表示形式,以找到其他一些二进制数发送到屏幕硬件。

例如,如果计算机是8位Atari,则会找到8个二进制值来表示屏幕上的字符A

00000000
00011000
00111100
01100110
01100110
01111110
01100110
00000000

正如您所看到的,当图形硬件在屏幕上绘制时,二进制值将转换为暗像素和亮像素。

同样,无论我们在计算机中使用数字做什么,它都是以某种方式移动二进制值,对二进制值进行计算,并将它们转换为其他二进制值。

例如,如果您以 A 的字符代码作为输入,并希望将其显示为十进制数,则计算机会计算该数字的十进制表示为数字6(110)和5(101),将其转换为字符 600110110)和字符500110101),然后将它们转换为它们的图形表示形式。


9
这是一个很好的问题,它需要数年时间和几个博士学位才能完全解释清楚。我可以给你一个简单的答案,但要完全理解,你需要进行更多的研究。我建议你在这里参加麻省理工学院的一些免费在线课程here
在最低层次上,字母A和数字65实际上使用相同的0和1序列存储。如果我没记错的话是1000001。
计算机从内存中获取时决定它是什么。这意味着字母可以显示为数字,反之亦然。
计算机知道它正在寻找的内容是由程序员告诉它的。程序员说我想在某个位置存储一个数字,计算机就会去查找它。
让我们提升一个级别,因为现在很少有程序在这么低的级别上编程。其他程序(通常是将类似C++的代码转换成计算机可理解的代码的编译器)确保我们正在访问的位置实际上是我们说的那个位置。它们具有额外的信息,告诉它们这组1和0实际上是浮点类型(有小数点),而这一组是整数(没有小数点)。
然后,其他类型建立在这些类型之上,更大的整数、浮点数或字符串,编译器再次强制执行类型。
这是一种过度简化的说法,我意识到这里的一切并不完全正确,但它会让你走上正确的道路。您可以查看一些这些主题,以获得更好的了解: 指令与数据如何区分?

http://en.wikipedia.org/wiki/Computer_data_storage

处理器/寄存器/内存中的数据、地址和指令有何区别?

http://en.wikipedia.org/wiki/Reference_(computer_science)

希望这能让事情更清晰一些。如有需要,请随时要求澄清!

1
在这个答案的基础上,你拥有了二进制,它由0和1组成,并直接在硬件上运行。再进一步的抽象将其转化为汇编语言,其中包含简单的指令,如ADD,SUB,DIV,MUL等,并解释了*二进制应该如何交互。这仍然非常容易出错,最终你会得到具有语法和语法的简单编程语言,然后将其编译成汇编语言和二进制代码,将人类语言翻译成机器语言。 - Kyle Baran

5
那么计算机如何区分“Z”和“892631”呢?
其实计算机并不能区分它们。对于计算机来说,所有的东西都是由0和1组成的。只有在处理器被告知如何处理这些0和1之后,这些原始位才会具有意义!
举个例子,我可以创建一个变量x,并将它的值设为0b01000001(0b表示"我正在用二进制描述一个数字")。我可以要求处理器帮我将变量x打印到屏幕上。但是,在此之前,我必须首先告诉处理器什么是x!
printf("%d", x); // this prints the decimal number 65

printf("%c", x); // this prints the character A

单独的x并没有意义,只是代表原始比特01000001。但作为程序员,我的工作是告诉计算机x实际上代表什么。


2

计算机在存储字母/特殊字符时只使用7位,而在存储数字时则使用一个字节的全部8位。

让我们以“A”和“65”为例。

65/2 -- 商是32,余数是1 1 2的0次方是1

32/2 商是16,余数是0 01

16/2 商是8,余数是0 001

8/2 商是4,余数是0 0001

4/2 商是2,余数是0 00001

2/2 商是1,余数是0 1000001 2的6次方是64

                             =========
                             1000001 binary repressents 65

A字母的ASCII值以二进制格式存储为01000001(它只使用7位,第8位用于字母和特殊字符时存储为0)。

希望这能帮到您。


UTF-8是一种广泛使用的字符编码,包括“特殊字符”和非拉丁字母表中的字母。它使用所有8位变长编码(每个字符1到4个字节)。前导位设置为1的数量=多字节字符中的总字节数。https://en.wikipedia.org/wiki/UTF-8#Description - Peter Cordes
你关于“只有7位用于存储字母/特殊字符”的说法是错误的。过时的7位US-ASCII代码是为数不多的符合此要求的代码之一。你喜欢的Windows、Linux或MacOS系统很可能使用Windows1252、许多ISO-8859变体或UTF-8中的一个,它们都使用完整的8位代码集。顺便说一句,还有5位代码和一些奇特的代码,比如https://en.wikipedia.org/wiki/DEC_Radix-50。 - Adrian W

2
让我们先讨论一些基础知识:
1. 假设你的硬盘只是一个铝制圆形板,上面有许多微小的孔洞/斑点(只能在显微镜下看到)。每个斑点都是由8位组成的字节组合而成的小孔洞(1位是1个孔洞)。 2. RAM类似于硬盘,但它是由硅制成的半导体,因此可以将信息存储为电场,并为每个字节分配地址,因此速度更快。 3. 计算机将您通过键盘输入的所有信息存储在硬盘中,以磁脉冲的形式表示(用1表示),如果没有信息,则该点(一个微小的孔洞)为空,称为0。
现在让我们来讨论您问题的第一部分 - 您能给我展示一些例子吗?比如计算机如何将字母“A”转换为二进制?
4. 例如,您通过键盘输入字符'A'和'அ'。 5. 字符'A'在Unicode / ASCII中表示为65,即二进制的01000001。操作系统将A映射到二进制。您输入的这个字符'A'现在以01000001的形式存储在硬盘中,并将出现在8个不同的位置(例如,在第七位中,左侧数字0没有磁脉冲,第7位有磁脉冲等)。 6. 在RAM的情况下,它以电脉冲的形式存储信息,因此当电源关闭时,RAM会丢失所有信息。
现在,您在RAM或硬盘上看到的所有内容都是给定字节中的能量或无能量,并且我们将其称为二进制格式(让我们将其称为0表示无能量,1表示有能量)。
现在由编译器决定如何存储。如果是AMD处理器/Windows操作系统上的C编译器,则将值存储在2个字节中(一个字节为5,一个字节为6)。存储值为5的字节将在6的右侧(如果是AMD处理),这被称为低端序。C程序不支持字符'அ',因为需要多于1个字节来存储国际字符。
如果是Java编译器,则使用长度可变的4个字节,称为UTF-16。对于字母'A',只需1个字节即可,因为Unicode / ASCII表示为65。而如果要存储国际语言字符(例如泰米尔语中的A类似的'அ'),则相应的Unicode值为2949,相应的二进制值为11100000 10101110 10000101(3个字节)。Java可以轻松存储和读取'A'和'அ'。
现在想象一下,您使用Java / Windows / AMD处理器将字符'அ'作为类型字符(Char)存储在硬盘中。
现在想象一下,您想使用C程序作为Char读取此内容。 C编译器仅支持ASCII而不是完整的Unicode集。在这里,C将读取上述3个字节的最右侧(10000101)字节(对于char类型,它会读取1个字节),屏幕上会显示什么?如果您要求程序打印,您的C程序将读取此1个字节而不会出现任何问题,并在屏幕上绘制此�。因此,编译器是区别制造者。
现在让我们讨论您问题的第二部分:当计算机看到二进制代码时,它们如何知道那长串0和1代表数字、单词或指令?
现在,您正在将已编译的Java程序加载到RAM的文本和数据区域中(在高级别上,RAM被分成文本和数据区域)。现在,您要求处理器的ALU执行您的程序的一组指令,称为进程。
您已编译程序中的行是将数据从一个变量移动到另一个变量的指令。
当ALU执行第一个指令时,它进入RAM外部的相应寄存器。处理器具有用于数据和指令的一组寄存器。根据这个,ALU现在知道哪个寄存器是什么,然后执行您的指令。
希望这有所帮助。

2
这里有一些过于简化的地方,但也有一些错误。在同一段落中,您谈到Java使用UTF-16,然后说அ表示为11100000 10101110 10000101(3个字节)。显然这是不正确的,因为UTF-16将Unicode代码点编码为一个或多个2字节块。您展示的比特模式看起来像该代码点的UTF-8编码,基于第一个字节中的3个前导1位表示3字节字符。 - Peter Cordes
2
另外,“操作系统将A映射为二进制”有点奇怪。计算机内部一切都是二进制的。映射的输入是来自键盘的扫描码(或USB键盘驱动程序)。终端驱动程序或GUI事件传递器将按键映射到它们的ASCII或UTF-8或UTF-16代码,或任何字符集。或者将其映射到Unicode代码点,然后从那里编码为UTF-8。 - Peter Cordes
谢谢,彼得。你的观点是正确的。我非常清楚给定的按键如何转换为11位扫描码(起始位、数据、奇偶校验位和停止位),并作为比特流发送到PS/2或USB上,然后根据我们在控制面板中选择的字符集映射到相应的ASCII或UTF。我不想深入研究这个问题,所以我过于简化了它,称其为操作系统。 - Siva
Peter,再次感谢。我又一次过于简化了国际字符需要3个字节的事实,因为相应的十进制值是2949,十六进制是0xb85。我的意思是它至少需要3个字节,但从技术上讲,如果它是使用一组2个字节的UTF-16,则需要4个字节。在这种情况下,它占用4个字节,最左边的一个将是零。大多数人认为Java是UTF-8,但在字符或字符串的情况下并非如此,正如你所说的那样,它是UTF-16。谢谢。我会使我的文章更加精确。 - Siva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接