目录
编程计算2的1024次方
——2023年迅雷面试题
一、累积法
(1)“累乘积”算法模型
①定义一个变量并赋初值为 1
②为每一个数据项提供一个通式
③循环遍历每一个数据项,并用初值为 1的变量累乘(*=)每一个数据项
④循环结束后,初值为 1的变量的值就是累乘的结果
(2)代码实现
#include<stdio.h>
int main(int argc,char** argv)
{
int sum = 1;
for(int i=0;i<1024;i++)
{
sum*=2;
}
printf("2^1024=%d\n",sum);
return 0;
}
(3)结果分析
(4)二进制角度分析
①在二进制中,int 类型的值是一个 32 位的二进制数。
②当 result 不断乘以 2 时,它的二进制表示会不断左移。
③最终,所有有效位都被移出,剩下的都是 0,因此 result 变为 0。
二、位移法
(1)“位移”算法模型
位运算符<<(按位左移) 左移n位,数据乘以2的n次方
a=60 a<<2 a=240
32 << 2 = 32 * 2^2 = 128
16 << 4 = 16 * 2^4 = 256
7 << 2 = 7 * 2^2 = 28
(2)代码实现
#include<stdio.h>
int main(int argc,char* argv)
{
int sum = 1;
sum <<=1024;
printf("%d\n",sum);
return 0;
}
(3)结果分析
warning: left shift count >= width of type [-Wshift-count-overflow]
sum = sum << 1024;
①程序最终输出的结果是 1,很可能是编译器在处理这个未定义行为时,把位移量进行了取模操作。
②也就是将 1024 对 int 类型的位数 32 取模,即 1024 % 32 = 0。
③这样一来,sum << 1024 实际上就相当于 sum << 0,而任何数左移 0 位都还是其本身,所以 sum 的值依旧是 1。
三、long double 类型
(1)long double 类型
①%Lf 表示要输出一个 long double 类型的变量
②%lf 表示要输出一个 double 类型的变量
③.0 表示不输出小数部分
(2)代码实现
#include<stdio.h>
int main(int argc,char* argv)
{
long double sum=1;
for(int i=0;i<1024;i++)
{
sum*=2;
}
printf("%.0lf\n",sum);
return 0;
}
(3)优缺点分析
<优点>
①实现简单:代码逻辑直观,无需复杂数据结构与算法,便于理解,可快速实现计算
②可处理大数:相比 float 和 double,long double 精度更高、范围更大,一定程度上能应对 2 的 1024 次方计算
<缺点>
①精度损失:浮点数以二进制存储运算,对 2 的 1024 次方这类大数无法精确表示每一位,可能存在“四舍五入”情况
②可能溢出:2 的 1024 次方极大,在不同的编译环境中可能超出 long double 表示范围,造成溢出
③不适精确计算:在对精度要求高的场景中不适用,需要考虑其他方式
四、字符数组模拟大整数乘法
(1)理论分析
(2)代码实现
#include <stdio.h>
#include <string.h>
// 反转字符串函数
void reverse(char* result_str)
{
// 计算字符串的长度
int length = strlen(result_str);
// 遍历字符串的前半部分
for (int i = 0; i < length / 2; i++)
{
// 交换当前位置和对称位置的字符
char temp = result_str[i];
result_str[i] = result_str[length - 1 - i];
result_str[length - 1 - i] = temp;
}
}
// 计算 2 的 n 次方
void calculate_t(int idex, char *result_str, int result_size)
{
int carry = 0; // 进位标志
int result_length = 1;
// 循环 idex 次
for (int i = 0; i < idex; i++)
{
carry = 0;
for (int j = 0; j < result_length; j++)
{
// 将字符转换为对应的数字
int digit = result_str[j] - '0';
// 乘以 2 并加上进位
digit = (digit * 2) + carry;
// 计算新的进位
carry = digit / 10;
// 将结果的个位转换为字符存回字符串
result_str[j] = digit % 10 + '0';
}
// 处理最后的进位
while (carry > 0)
{
// 检查数组是否还有空间存储新的数字
if (result_length >= result_size - 1)
{
printf("数组空间不足,无法存储完整结果!\n");
return;
}
// 将进位的个位转换为字符存入结果字符串
result_str[result_length++] = carry % 10 + '0';
// 进位除以 10,处理更高位的进位
carry /= 10;
}
}
// 添加字符串结束符
result_str[result_length] = '\0';
reverse(result_str);
}
int main()
{
int idex = 1024;
char result[2048] = {'1'};
int result_size = sizeof(result);
calculate_t(idex, result, result_size);
printf("2 的 %d 次方的结果是:\n%s\n", idex, result);
return 0;
}
(3)扩展
引入“位移”算法模型:
位运算符<<(按位左移)
结果存放在字符数组中