人类的手指数量是十进制的基础,基于手指的计数方式使得十进制(decimal )作为计算的基本体系成为了一种自然而然的选择。
一个十进制数的整数是个位、十位、百位、千位等的组合。例如,123(一百二十三)的个位数是3,十位数是2,百位数是1。
$ 123=1×10^2+2×10^1+3×10^0 $表达的是:
1 | 2 | 3 |
---|---|---|
百位 | 十位 | 个位 |
其中,$ b_i $∈(0,1,2,3,4,5,6,7,8,9),(i=0,1,2,…,m) 例如,$ 0.123=1×10^{-1}+2×10^{-2}+3×10^{-3} $
这可以进一步简化为两个求和公式的组合:
$ \sum_{i=0}^{n} a_i \times 10^i + \sum_{j=1}^{m} b_j \times 10^{-j} $ ——(1-3)
这里,$ \sum $ 表示求和,$ i $ 和 $ j $ 是索引变量,分别用于遍历整数部分和小数部分的每一位。
用二进制(Binary)表达一个数,二进制数是一种数制系统,它只使用两个数字:0和1。在二进制中,每一位(bit)的值是前一位的两倍(在十进制中表示)。最右边的位是最低位(也称为“0位”或“个位”),其值就是它本身(0或1)。然后,向左移动,每一位的值都是前一位的两倍。
例如一个数写为:$ a_n…a_i…a_0 $,其中,$ a_i $∈(0,1),实际意义是:
$ a_n \times 2^n + a_{n-1} \times 2^{n-1} + \ldots + a_1 \times 2^1 + a_0 \times 2^0 $
或者更一般地表示为:
$ a_n \times B^n + a_{n-1} \times B^{n-1} + \ldots + a_1 \times B^1 + a_0 \times B^0 $
(其中B是基数,对于二进制来说B=2)
例如,二进制数1011转换为十进制数的计算过程如下:
$ 1011_{(2)} = 1 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 1 \times 2^0 $
$ = 1 \times 8 + 0 \times 4 + 1 \times 2 + 1 \times 1 $
$ = 8 + 0 + 2 + 1 $
$ = 11_{(10)} $
所以,二进制数1011等于十进制数11。
可以用八进制(Octal)表达一个数,八进制数是一种数制系统,它使用八个数字:0, 1, 2, 3, 4, 5, 6 和 7。在八进制中,每一位(digit)的值是前一位的八倍(在十进制中表示)。
给出公式:
$ a_n \times 8^n + a_{n-1} \times 8^{n-1} + \ldots + a_1 \times 8^1 + a_0 \times 8^0 $
或者更一般地表示为:
$ a_n \times O^n + a_{n-1} \times O^{n-1} + \ldots + a_1 \times O^1 + a_0 \times O^0 $
(其中8, O是基数,对于八进制来说O=8,但通常我们用8来表示八进制的基数,以避免与十进制中的0混淆。不过,在你的公式中,为了区分,你使用了O,这是可以理解的。)
注意,基数上的幂(如$ 8^n $)仍用十进制表达,这是数学上的常规做法。
现在,让我们来个例子:
八进制数127转换为十进制数的计算过程如下:
首先,按照八进制的规则,每一位上的数字乘以8的该位权重(从0开始计数):
$ 127_{(8)} = 1 \times 8^2 + 2 \times 8^1 + 7 \times 8^0 $
然后,计算这些乘积的和:
$ = 1 \times 64 + 2 \times 8 + 7 \times 1 $
$ = 64 + 16 + 7 $
$ = 87_{(10)} $
所以,八进制数127等于十进制数87。
在实际应用中,八进制数经常用于计算机科学中,特别是在处理文件权限和某些类型的计算机内存地址时。
其实中国长期采用十六进制(Hexadecimal)作为重量的进制。十六进制数是一种数制系统,它使用十六个数字:0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, 和 F。其中,A 到 F 分别表示十进制的 10 到 15。在十六进制中,每一位(digit)的值是前一位的十六倍(在十进制中表示)。
给出的公式:
$ a_n \times H^n + a_{n-1} \times H^{n-1} + \ldots + a_1 \times H^1 + a_0 \times H^0 $
它表示了一个十六进制数如何被转换为十进制数。在这个公式中:
注意,虽然 A 到 F 在十六进制中表示的是十进制的 10 到 15,但在进行数学运算时,我们通常会将它们转换为十进制数。然而,在表示十六进制数时,我们仍然使用 A 到 F 这些符号,以保持十六进制数的格式。
例如,十六进制数 1A3F 转换为十进制数的计算过程如下:
$ 1A3F_{(16)} = 1 \times 16^3 + A \times 16^2 + 3 \times 16^1 + F \times 16^0 $
$ = 1 \times 4096 + 10 \times 256 + 3 \times 16 + 15 \times 1 $
$ = 4096 + 2560 + 48 + 15 $
$ = 6719_{(10)} $
所以,十六进制数 1A3F 等于十进制数 6719。
在实际应用中,十六进制数经常用于计算机科学中,特别是在处理颜色代码、内存地址和某些类型的计算机指令时。
本题考查的是十进制数转换为二进制数的方法。
十进制数转换为二进制数,采用“除2取余,逆序排列”法。
综上
189的二进制是10111101
128的二进制是10000000
510的二进制是111111110
1023的二进制是1111111111
本题考查的是二进制数转换为十进制、八进制、十六进制和三进制数的方法。
从右到左,二进制数的每一位分别代表 $ 2^0, 2^1, 2^2, ... $ 的值。
10101011(B)
= $ 1 \times 2^7 + 0 \times 2^6 + 1 \times 2^5 + 0 \times 2^4 + 1 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 1 \times 2^0 $
= 128 + 0 + 32 + 0 + 8 + 0 + 2 + 1
= 171
从右到左,每三位二进制数可以转换为一个八进制数(不足三位时,在前面补0)。
10101011(B) 可以分成 001 010 101 110(前面补0以满足三位一组)。
001 → 1(O)
010 → 2(O)
101 → 5(O)
110 → 6(O)
组合起来就是 1256(O)。但注意,我们最初没有补0,所以正确的八进制表示是 253(O)(直接按8位分)。
从右到左,每四位二进制数可以转换为一个十六进制数(不足四位时,在前面补0)。
10101011(B) 可以直接转换(8位刚好是2个十六进制数)。
1010 → A(H)
1011 → B(H)
组合起来就是 AB(H)。
步骤
将二进制数转换为十进制数:
= $ 1 \times 128 + 0 \times 64 + 1 \times 32 + 0 \times 16 + 1 \times 8 + 0 \times 4 + 1 \times 2 + 1 \times 1 $
= 128 + 32 + 8 + 2 + 1
= 171
$ ( 171 \div 3 = 57 ) 余 0 $
$ ( 57 \div 3 = 19 ) 余 0 $
$ ( 19 \div 3 = 6 ) 余 1 $
$ ( 6 \div 3 = 2 ) 余 0 $
$ ( 2 \div 3 = 0 ) 余 2 $
将余数从下往上排列,得到三进制数:20100
结果
10101011(B) = 20100(T)(T表示三进制)
综上,二进制数10101011转换为十进制是171,八进制是253,十六进制是AB,三进制是202022。
127(八进制)
$ =1×10^2+2×10^1+7×10^0 $(八进制的127)
$ =001\space010\space111 $ (写成二进制,每3位一组成八进制的一位数)
$ =0\space0101\space0111 $ ( 每4位组成十六进制的一位数)
$ =0\space\space5\space\space7 $ (十六进制的057)
$ =0×H^2+5×H^1+7×H^0 $(十六进制)
从十六进制换算为十进制
$ =0×16^2+5×16^1+7×16^0 $(把十六进制换算为十进制)
$ =5×16+7 $(十进制)
$ =87 $(十进制)
或直接从八进制换算为十进制:
$ =1×8^2+2×8^1+7×8^0 $(换算为十进制)
$ =64+16+7 $
$ =87 $(十进制)
事实上,可以定义任何一种进制,例如,三进制、七进制等,从而形成不同的进制体系。我们日常生活中的12或24的小时进制,60秒为1分的60进制,等等。
示例:1234 + 5678= ?
通过手写运算可知,1234 + 5678 = 6912
春秋战国;“筹算”的使用已经非常普遍了
珠算(珠算文化),是以算盘为工具进行数字计算的一种方法,是中国古代众多的科技发明之一,系由“筹算”演变而来。国家级非物质文化遗产之一。
(1)以算珠靠梁表示记数开始。每颗上珠当做是五,每颗下珠当做是一,空档表示零。以档表示数位,高位在左,低位在右。
(2)在置数前,算盘上不能有任何算珠靠梁。置数时,应先由高到低(从左向右)定位,将预定数字按位逐档拨珠靠梁。
(3)珠算加减从左向右进行,可边看边打,在被加数(被减数)上连加(连减)几个数,盘面就会显示结果。
(4)乘除运算在盘上使用大九九口诀的加减运算。
传统加减法是通过口诀进行计算的,而珠算加减法依据“五升十进制”原理,通过对5与10两数的分解和合成,利用“凑数”与“补数”进行计算的。
凑数(1+4=5,2+3=5,3+2=5,4+1=5)
补数(1+9=10,2+8=10,3+7=10,4+6=10,5+5=10,6+4=10,7+3=10,8+2=10,9+1=10)
计算机器的发展:
构造一个8位二进制加减法器通常涉及使用基本的逻辑门(如AND、OR、XOR、NOT)以及半加器(Half Adder, HA)和全加器(Full Adder, FA)的组合。这里,我将用图示如何构建一个8位二进制加减法器,包括必要的组件和它们之间的连接。
编程,简单来说,就是编写一系列指令或代码的过程,这些指令或代码能够指导计算机进行各种操作。这些操作可能包括数据处理、逻辑判断、输入输出等。编程的目的是让计算机能够根据人类的意愿自动完成各种任务,从而提高工作效率和准确性。
可编程计算机器,顾名思义,是指能够依据预设的程序自动执行计算任务的机器。这种机器的核心在于其能够根据用户编写的程序,一步一步地执行计算步骤,从而完成复杂的计算任务。
Ada Lovelace认为,巴贝奇的分析机(一种早期的计算机器)与之前的计算机器的根本差别在于其能够事先编写一系列的计算步骤,这些步骤共同构成了一个程序,使得分析机能够执行复杂的计算。这一观点奠定了现代计算机器可编程性的基础。
综上所述,可编程计算机器通过预设的程序自动执行计算任务,而一个完整的程序则包含计算步骤、计算符号、运算的变量、计算公式、初始数据、中间(变量)数据和最终结果等基本要素。图灵的程序和冯诺依曼计算机结构为现代计算机的发展奠定了坚实的基础。
程序的基本要素是构成程序完整性和功能性的关键组成部分。这些要素共同协作,确保程序能够按照预期执行并完成任务。以下是程序的基本要素:
一元一次方程是指只含有一个未知数(通常表示为 $ x $),且未知数的次数为1的方程。其一般形式为:
$ ax + b = 0 $
其中 $ a $ 和 $ b $ 是已知数,且 $ a \neq 0 $(因为如果 $ a = 0 $,则方程退化为常数方程,不再是一元一次方程)。
求解一元一次方程的步骤如下:
具体步骤可以表示为:
$ ax + b = 0 $
移项得:
$ ax = -b $
然后两边同时除以 $ a $ 得:
$ x = -\frac{b}{a} $
使用编程语言求解一元一次方程,可以通过以下步骤实现:
以下是一个用C语言编写的求解一元一次方程的程序示例:
#include <stdio.h>
int main() {
double a, b, x;
// 输入a和b的值
printf("请输入一元一次方程的系数a和常数项b(用空格分隔): ");
scanf("%lf %lf", &a, &b);
// 检查a是否为零,避免除以零的错误
if (a == 0) {
printf("输入错误,a不能为0,否则为非法一元一次方程。\n");
}
} else {
// 计算x的值
x = -b / a;
// 输出结果
printf("方程的解是: x = %.2lf\n", x);
}
return 0;
}
scanf
函数从用户那里接收 $ a $ 和 $ b $ 的值。printf
函数将计算得到的 $ x $ 值输出给用户,保留两位小数。这个程序能够正确处理一元一次方程的求解问题,并给出适当的错误提示。
初中学习过的一元二次方程
$ ax^2+bx+c=0 $
其中,a,b,c 是实数。(注:等号在数学中和在程序中都是等号,但程序中需要用=号表示赋值,要注意算术中和程序中'='的区别)
这样,就有:delta=b∗b−4∗a∗c
1. ∆是个希腊字母,计算机的(英文)键盘没有这个符号,可以写为英文delta表示。
2. 键盘上没有乘法符号×,用*替代;
3. 除法符号÷用/替代
/* 用#include 引入程序包:
1.标准输入输出stdio.h
2.数学库:math.h, 里面有开平方sart(x)的函数
*/
#include <stdio.h>
#include <math.h>
int main() // 声明一个主函数
{
// 下面声明计算中用的变量
double a, b, c; // 声明 一元二次方程的三个系数变量为双精度浮点数
double x1, x2; // 声明 一元二次方程的两个根,为双精度浮点数变量
double Delta; // 声明一个中间临时变量,用于计算b*b-4*a*c
// 变量声明区结束
// 接收用户的输入,计算机得到:a,b,c三个值
printf("请输入一元二次方程的三个系数:\n"); //输入前的提示
printf("请输入系数 a = \t"); //输入的提示
scanf("%lf", &a); //输入语句
printf("请输入系数 b = \t"); //输入的提示
scanf("%lf", &b); //输入语句
printf("请输入系数 c = \t"); //输入的提示
scanf("%lf", &c); //输入的提示
//验证一下a,b,c三个系数是否输入正确?
printf("a=%.2f,\nb=%.2f,\nc=%.2f\n", a, b, c);
// 输入部分结束
//计算机开始计算:
//1.先计算出delta的值;
Delta = b * b - 4 * a * c;
// 分别考虑a,b,c和delta 的情况,分别做根的计算
if (fabs(a) >= 0.00000001) //判断a是否为0? 为安全起见,最好用 if (abs(a) >= 0.0000001),即,a大于一个很小的数
//abs(x)是math.h里额一个函数,即,求出x的绝对值
{
if (Delta < 0) //判断是否有实数解?
{
printf("该方程式无实数解!\n");
/* 当Delta小于0时,方程无实数解,但是可以有虚数解。
realpart = - b/(2*a); //实部
mipart = sqrt(-Delta) / (2*a);
printf("方程有两个共轭复根:\n");
printf("x1 = %.2f+%.5fi\n",realpart,mipart);
//人为地加了i,以表示虚部
printf("x2 = %.2f-%.5fi\n",realpart,mipart);
*/
}
else if (fabs(Delta) < 0.0000001) //安全起见,用if (abs(Delta) < 0.0000001), Delta小于一个很小的数即Delta=0
{
x1 = x2 = -b / (2 * a);
printf("方程有两个相等的根:\nx1=x2 = %.2f\n", x1); //输出 计算结果
}
else
{
Delta = sqrt(Delta); // sqrt是math.h里的函数,用来开平方
x1 = (-b + Delta) / (2 * a); //得到第一个根
x2 = (-b - Delta) / (2 * a); //得到第一个根
printf("方程的两个根为\nx1 = %.2f,\nx2 = %.2f\n", x1, x2); //输出 计算结果
}
}
else if (fabs(b) >= 0.00000001) //安全起见,用if (abs(b) > 0.0000001), 即,b大于一个很小的数即,b不为0
{
x1 = -c / b;
printf("该方程是一元一次方程,根 x =%.2f\n", x1); //输出 计算结果
}
else if (fabs(c) < 0.0000001)//安全起见,用if (abs(c) < 0.0000001), 即,c小于一个很小的数即c=0
printf("x可以是任意值。\n"); //输出 计算结果
else
printf("该方程不成立。\n"); //输出 计算结果
return 0;
}
初中学习过的一元二次方程
$$
\begin{cases}
a_1x + b_1y = c_1 \
a_2x - b_2y = c_2
\end{cases}
$$
C语言,写 $ a_1,a_2 $ 太麻烦,将其改写为:
$$
a1x+b1y==c1 \
a2x+b2y==c2
$$
注:C语言中“==”表示恒等,“=”表示赋值(传递值),其中,a1,a2,b1,b2,c1,c2 是实数。
$$
\begin{cases}
a_1x + b_1y = c_1 \quad \text{①} \
a_2x - b_2y = c_2 \quad \text{②}
\end{cases}
$$
首先确定① ②哪个方程更容易解除一个变量,假设由方程①得到方程③。
$$
y = \frac{c_1 - a_1x}{b_1} \quad \text{③}
$$
$$
x = \frac{c_2 - b_2 (\frac{c_1 - a_1 x}{b_1})}{a_2}=\frac{c_2b_1−b_2c_1}{b_1a_2−b_2a_1} \quad \text{④}
$$
判断$ d=b_1a_2−b_2a_1 $
$$
y=\frac{c_1a_2−a_1c_2}{b_1a_2−b_2a_1}
$$
#include <stdio.h>
#include <math.h>
#define EPSILON 1e-6
int main()
{
float a1, b1, c1, a2, b2, c2, x, y, d;
// 读取方程组系数
printf("请输入方程组的系数:\n");
printf("第一个方程的 a1、b1、c1:");
if (scanf("%f%f%f", &a1, &b1, &c1) != 3) {
printf("输入错误,请输入三个浮点数。\n");
return 1;
}
printf("第二个方程的 a2、b2、c2:");
if (scanf("%f%f%f", &a2, &b2, &c2) != 3) {
printf("输入错误,请输入三个浮点数。\n");
return 1;
}
d = b1 * a2 - b2 * a1;
// 解方程组, 计算机中浮点数不等于0,使用绝对值fabs(d)<1e-6无限接近0来表述,
if (fabs(d) < EPSILON) {
printf("方程组无解!\n");
} else {
x = (c2 * b1 - b2 * c1) / d;
y = (c1 * a2 - a1 * c2) / d;
printf("方程组的解为:x=%.2f, y=%.2f\n", x, y);
}
// system("pause");
return 0;
}
引用其他人的程序
#include <>
- 使用有意义的变量名和注释来提高代码的可读性。
- 避免在条件表达式中进行复杂的计算或赋值操作,以免混淆逻辑。
- 在可能的情况下,使用位运算代替算术运算以提高性能。
- 避免不必要的类型转换和重复计算,以减少 CPU 的负担。
- 在使用数学库函数时,检查输入参数的有效性以避免运行时错误。
- 在进行除法运算时,确保除数不为零以避免除零错误。
- 对于用户输入的数据,进行必要的验证和过滤,以防止恶意输入导致的程序崩溃或安全问题。
- 使用函数将代码模块化,以提高代码的可维护性和可重用性。
- 将相关的函数和数据封装在结构体或类中,以形成更清晰的代码结构。
- 使用条件编译指令来包含或排除特定的代码段,以适应不同的编译环境或需求。
综上所述,C 语言的运算与选择结构是编程中的基础部分。通过深入理解这些结构的工作原理和用法,结合良好的编程习惯和最佳实践,可以编写出更高效、更可读、更安全的 C 语言程序。