# 各种进制
#include <iostream>
#include <string>
using namespace std;
// 十进制转其他进制
string decimalToBase(int n, int base) {
string digits = "0123456789ABCDEF"; // 可根据需要扩展到更多进制
string result = "";
while (n > 0) {
int remainder = n % base;
result = digits[remainder] + result;
n = n / base;
}
return result;
}
// 其他进制转十进制
int baseToDecimal(string num, int base) {
string digits = "0123456789ABCDEF"; // 可根据需要扩展到更多进制
int result = 0;
int power = 0;
for (int i = num.length() - 1; i >= 0; --i) {
int value = digits.find(num[i]);
result += value * pow(base, power);
power++;
}
return result;
}
// 其他进制之间的转换
string baseConversion(string num, int fromBase, int toBase) {
int decimal = baseToDecimal(num, fromBase);
string result = decimalToBase(decimal, toBase);
return result;
}
int main() {
// 十进制转二进制
cout << decimalToBase(10, 2) << endl; // 输出: 1010
// 二进制转十进制
cout << baseToDecimal("1010", 2) << endl; // 输出: 10
// 二进制转十六进制
cout << baseConversion("1010", 2, 16) << endl; // 输出: A
// 十六进制转八进制
cout << baseConversion("A", 16, 8) << endl; // 输出: 12
return 0;
}
# 二进制的深入探究
在将小数转换为二进制时,需要使用一种特殊的表示方法,称为浮点数表示法或二进制浮点表示法。这是因为大多数小数无法在有限位的二进制中准确表示。
常见的浮点数表示方法是 IEEE 754 标准,它定义了单精度浮点数(32 位)和双精度浮点数(64 位)的格式。下面我们以单精度浮点数为例,介绍如何将小数转换为二进制。
-
将小数的整数部分转换为二进制:将小数的整数部分不断除以 2,并记录每次的余数,直到商为 0 为止。然后将这些余数倒序排列,得到整数部分的二进制。
-
将小数的小数部分转换为二进制:将小数的小数部分不断乘以 2,并取出整数部分作为二进制的一位。然后将剩余的小数部分再次乘以 2,继续取整数部分,直到小数部分为 0 或达到所需的精度。
-
组合整数部分和小数部分的二进制:将整数部分的二进制与小数部分的二进制进行组合,用一个特定的标志位来表示小数点的位置。
需要注意的是,由于二进制是有限位的,对于某些小数,转换为二进制后可能无法精确表示。这可能会导致舍入误差和精度损失。因此,在进行浮点数计算时,需要注意处理这些舍入误差。
以下是一个示例,将小数 0.625 转换为单精度浮点数的二进制表示:
- 整数部分:0 的二进制表示为 0。
- 小数部分:0.625 乘以 2 的结果是 1.25,取整数部分 1,剩余小数部分为 0.25。继续乘以 2,得到整数部分 0,剩余小数部分为 0.5。再次乘以 2,得到整数部分 1,剩余小数部分为 0。小数部分转换为二进制为 "101"。
- 组合整数部分和小数部分:整数部分为 0,小数部分为 "101",小数点位置为 3(从小数部分的左边开始计数)。所以 0.625 的二进制表示为 0.101。
请注意,实际上,IEEE 754 标准对于浮点数的表示和转换有更复杂的规则,涉及到指数位、符号位等。这里只给出了简化的示例来说明基本的过程。
#include <iostream> | |
#include <string> | |
std::string decimalToBinary(double decimal) { | |
if (decimal < 0 || decimal >= 1) { | |
return "Invalid decimal"; | |
} | |
std::string binary = "0."; | |
while (decimal > 0) { | |
decimal *= 2; | |
int bit = static_cast<int>(decimal); | |
binary += std::to_string(bit); | |
decimal -= bit; | |
} | |
return binary; | |
} | |
int main() { | |
double decimal = 0.625; | |
std::cout << decimalToBinary(decimal) << std::endl; // 输出:0.101 | |
return 0; | |
} |
对于负数的二进制表示,通常有两种方法:原码和补码。
- 原码表示法
在原码表示法中,一个负数的二进制表示的最高位为符号位,0 表示正数,1 表示负数。其他位按照正数的二进制表示方法来表示绝对值大小。例如,-3 的原码为 10000011。
原码表示法最大的问题就是加法运算不方便,需要考虑符号位以及进位等情况。因此,补码表示法被广泛使用。
- 补码表示法
在补码表示法中,一个负数的二进制表示的计算方式和正数不同,需要先求出该数的绝对值二进制表示,然后取其反码,再将结果加 1。其中,反码表示方式为将二进制表示中每个位取反(0 变为 1,1 变为 0),符号位不变。
例如,-3 的补码为 11111101。具体过程如下:
-3 的绝对值为 3,其二进制表示为 00000011;
对该二进制表示取反得到 11111100,这就是 - 3 的反码;
将反码加 1,即得到补码 11111101。
注意,在补码表示法中,最高位的符号位不参与运算,只用来表示正负。加减乘除运算都是直接在补码上进行,无需特别考虑符号位的影响。
对于负数的二进制表示,无论是原码还是补码,其最高位均为 1,因此,在计算机中表示负数时,需要占用更多的位数。例如,在 8 位二进制中,可以表示 - 128 到 127 之间的整数,其中 0 到 127 为正数,128 到 255 为负数。
# 逻辑命题与位运算
逻辑命题是一个陈述句,可以被判定为真或假的陈述。它通常用于逻辑推理和数学证明中。
以下是一些常见的逻辑命题形式:
-
"今天是星期天":这是一个具体的命题,要么为真(如果今天确实是星期天),要么为假(如果今天不是星期天)。
-
"2 加 2 等于 4":这是一个数学命题,为真。
-
"地球是平的":这是一个错误的命题,为假。
-
"如果下雨,那么地面湿润":这是一个条件命题,如果下雨,则地面湿润,否则为假。
-
"所有的猫都有尾巴":这是一个普遍命题,如果所有的猫都有尾巴,则为真,否则为假。
逻辑命题可以通过观察、推理或实验来确定其真值。在逻辑推理中,根据逻辑规则和前提,我们可以推导出新的命题。逻辑命题在数学、哲学、计算机科学等领域中都发挥着重要的作用。
位运算是一种操作二进制数的运算,它直接对二进制数的位进行操作,而不是像普通四则运算那样对数值进行操作。位运算符号包括按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)和右移(>>)。
下面是每种位运算符号的具体含义和用法:
-
按位与(&):将两个二进制数的每一位进行运算,只有当两个对应位都为 1 时,结果才为 1,否则为 0。例如,0b1011 & 0b1100 = 0b1000。
-
按位或(|):将两个二进制数的每一位进行运算,只要两个对应位中有一个为 1,结果就为 1,否则为 0。例如,0b1011 | 0b1100 = 0b1111。
-
按位异或(^):将两个二进制数的每一位进行运算,如果两个对应位相同,则结果为 0,否则为 1。例如,0b1011 ^ 0b1100 = 0b0111。
-
按位取反():将一个二进制数的每一位取反,即 0 变为 1,1 变为 0。例如,0b1011 = 0b0100。
-
左移(<<):将一个二进制数向左移动指定的位数。例如,0b1011 << 2 = 0b110100。
-
右移(>>):将一个二进制数向右移动指定的位数。例如,0b1011 >> 2 = 0b10。
位运算通常用于对某些位进行掩码、清除或设置。例如,要将一个二进制数的第 3 位清零,可以使用按位与运算符和掩码:num & 0b11110111。要将一个二进制数的第 4 位设置为 1,可以使用按位或运算符和掩码:num | 0b00001000。此外,位运算还可以用于实现一些高效的算法和数据结构,例如布隆过滤器和哈希表。