《编程思维与实践》1010.i-1进制I
题目
思路
将输入的十六进制数转化成二进制(利用字符串处理),
注意到 a + b i = k n ( − 1 + i ) n + k n − 1 ( − 1 + i ) n − 1 + . . . + k 0 a+bi=k_n(-1+i)^n+k_{n-1}(-1+i)^{n-1}+...+k_0 a+bi=kn(−1+i)n+kn−1(−1+i)n−1+...+k0 , 故也考虑用迭代处理.
p n + q n i = ( − 1 + i ) ⋅ ( p n − 1 + q n − 1 i ) + r n − 1 = r n − 1 − ( p n − 1 + q n − 1 ) + ( p n − 1 − q n − 1 ) i p_n+q_ni=(-1+i)·(p_{n-1}+q_{n-1}i)+r_{n-1}=r_{n-1}-(p_{n-1}+q_{n-1})+(p_{n-1}-q_{n-1})i pn+qni=(−1+i)⋅(pn−1+qn−1i)+rn−1=rn−1−(pn−1+qn−1)+(pn−1−qn−1)i
{ p n = r n − 1 − ( p n − 1 + q n − 1 ) p 0 = 0 , r 0 = k n q n = p n − 1 − q n − 1 q 0 = 0 \left\{ \begin{aligned} \quad p_n=r_{n-1}-(p_{n-1}+q_{n-1}) \quad p_0=0,r_0=k_n\\ q_n=p_{n-1}-q_{n-1} \quad q_0=0 \end{aligned} \right. {pn=rn−1−(pn−1+qn−1)p0=0,r0=knqn=pn−1−qn−1q0=0
注意的点:
1.十六进制转二进制时不能先将十六进制转十进制后再转成二进制,因为十六进制数对应的十进制数可能很大(超过long long范围),
十六进制转二进制时,每一位拆成四个二进制位,可通过&位运算实现,
但考虑到与左移后的1做&位运算来计算对应的二进制数时存储时倒序的,故可采用与逻辑右移后的1000做&位运算的方式存储.
2.a和b的类型应为long long.
代码
#include<stdio.h>
#include<string.h>
int main()
{
getchar();
getchar();
char s[100]; //将16进制变为2进制
scanf("%s",s);
char bit[1000];
int j=0;
for(int i=0;i<strlen(s);i++)
{
int d;
if(s[i]>='A') d=s[i]-'A'+10;
else d=s[i]-'0';
unsigned int flag=0x8; //0x8对应的二进制为1000 右移可以顺序存储每一位
while(flag)
{
if(d&flag) bit[j++]='1';
else bit[j++]='0';
flag=flag>>1;
}
}
bit[j]='\0';
//迭代计算a,b 利用循环
long long a,b;
long long p=0,q=0;
for(int i=0;i<strlen(bit);i++)
{
b=p-q;
a=(bit[i]-'0')-(p+q);
p=a;
q=b;
}
//控制输出
if(b==0) //没虚部
{
printf("%lld",a); //无论a是否为0由于没有虚部都必须输出
}
else
{
if(a!=0)//没实部不输出,有实部才输出
{
printf("%lld",a);
if(b>0)
{
printf("+");
}
}
if(b==1)
{
printf("i");
}
else if(b==-1)
{
printf("-i");
}
else{
printf("%lldi",b);
}
}
return 0;
}