定点小数原码一位乘(C++实现)
2012-10-16 23:03
281 查看
这学期在学计组,这里将用C++实现各种运算方法,其实那些算法应该是用电路硬件实现的,用高级语言来描述一遍也挺有意义。
说明:输入输出的小数均以机器数表示,数值位为4位。
运行结果:
之前用的是C来写,位运算太麻烦了,见下面的程序:
而C++的bitset类正好用于位的操作,很方便,在这个过程中,我也发现了bitset的不足,比如VS2010中bitset不能用unsigned long来初始化(没有相应的构造函数)。还有,为什么说复制构造函数、重载赋值运算符、析构函数要么都写,要么都别写呢?因为既然可以用一个对象来复制构造,那当然也适用于赋值操作,这是我的个人理解,甚至我认为把所有的构造函数的参数都最好拿来重载到赋值运算符,这是有需求的。
2012/10/17
把代码的结构方面改进了,更方便阅读。
输出:
说明:输入输出的小数均以机器数表示,数值位为4位。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <bitset> #include <string> using namespace std; void RightMove(bitset<6> &a, bitset<4> &b) // a,b联合右移 { b >>= 1; b[3] = a[0]; a >>= 1; } bitset<6> operator+(bitset<6> a, bitset<4> b) // 求a,b的算术和 { unsigned long long sum = a.to_ulong() + b.to_ulong(); //bitset<6> temp(sum); //return temp; return sum; // 调用了构造函数,待深究 } int main(int argc, char **argv) { string inputStr; while (cin >> inputStr) { const bitset<5> X(inputStr); // X是被乘数 const bool x0 = X[4]; // x0是X的符号位 const bitset<4> B(inputStr, 1, 4); // B是被乘数的绝对值 cin >> inputStr; const bitset<5> Y(inputStr); // Y是乘数 const bool y0 = Y[4]; // y0是Y的符号位 bitset<4> C(inputStr, 1, 4); // C是乘数的绝对值 #pragma region 核心算法 bitset<6> A; // A存放积(部分积) int cd = 4; // cd是计数器 while (cd--) { if (C[0]) { A = A + B; // 算术加 } RightMove(A, C); // A,C联合右移 } A[4] = x0 ^ y0; #pragma endregion 核心算法 cout << X << " * " << Y << " = " << A.to_string().substr(1) // 为了不输出A附加的符号位 << C << endl; } return 0; }
运行结果:
之前用的是C来写,位运算太麻烦了,见下面的程序:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> void RightMove(int *pHigh, int *pLow) { (*pLow) >>= 1; (*pLow) |= (*pHigh & 1) << 3; // 3为n-1 // *pLow右移进来的最高位一定是0 // 将low的高位置为high的低位(0|x) (*pHigh) >>= 1; } void SetSign(int *num, int a, int b) { if (a ^ b) { *num |= 1 << 4; } else { *num &= ~(1 << 4); } } void Print(char *XStr, char *YStr, int A, int C) { int i; char AStr[10]; char CStr[10]; _itoa(A, AStr, 2); _itoa(C, CStr, 2); printf("%s * %s = ", XStr, YStr); for (i = strlen(AStr); i < 5; i++) { printf("0"); } printf("%s", AStr); for (i = strlen(CStr); i < 4; i++) { printf("0"); } printf("%s\n", CStr); } int main(int argc, char **argv) { int X = 0; // X是被乘数 int x0 = 0; // x0是X的符号位 int B = 0; // B是被乘数的绝对值 int Y = 0; // Y是乘数 int y0 = 0; // y0是Y的符号位 int C = 0; // C是乘数的绝对值 int cd = 4; // cd是计数器 int A = 0; // A存放积(部分积) char XStr[10]; char YStr[10]; while (EOF != scanf("%s", XStr)) // 二进制输入 { X = (int)strtol(XStr, NULL, 2); x0 = XStr[0] - '0'; B = X & (~(1 << cd)); // 取绝对值,即将符号位置为0(x&0) scanf("%s", YStr); // 二进制输入 Y = (int)strtol(YStr, NULL, 2); y0 = YStr[0] - '0'; C = Y & (~(1 << cd)); #pragma region 核心算法 A = 0; // 注意初始化 cd = 4; while (cd--) { if (C & 1) { A += B; } RightMove(&A, &C); // A、C联合右移 } SetSign(&A, x0, y0); #pragma endregion 核心算法 Print(XStr, YStr, A, C); //printf("%s * %s = %s%s\n", XStr, YStr, _itoa(A, buffer, 2), _itoa(C, buffer, 2)); //从后向前压栈,最后算完才一起输出,输出将覆盖 } return 0; }
而C++的bitset类正好用于位的操作,很方便,在这个过程中,我也发现了bitset的不足,比如VS2010中bitset不能用unsigned long来初始化(没有相应的构造函数)。还有,为什么说复制构造函数、重载赋值运算符、析构函数要么都写,要么都别写呢?因为既然可以用一个对象来复制构造,那当然也适用于赋值操作,这是我的个人理解,甚至我认为把所有的构造函数的参数都最好拿来重载到赋值运算符,这是有需求的。
2012/10/17
把代码的结构方面改进了,更方便阅读。
// 定点小数源码一位乘 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <bitset> #include <string> using namespace std; const int n = 4; // 数值位位数 void RightMove(bitset<n + 2> &a, bitset<n> &b) // a,b联合右移 { b >>= 1; b[n - 1] = a[0]; a >>= 1; } bitset<n + 2> operator+(bitset<n + 2> a, bitset<n> b) // 求a,b的算术和 { unsigned long long sum = a.to_ulong() + b.to_ulong(); //bitset<6> temp(sum); //return temp; return sum; // 调用了构造函数,待深究 } bitset<2 * n + 1> TrueformOneMul(const bitset<n + 1> X, const bitset<n + 1> Y) { bitset<n + 2> A; // A放部分积(最后是积的高位) const bool x0 = X ; // x0是X的符号位 const bitset<n> B(X.to_ullong()); //截断符号位,B是被乘数的绝对值,其实也可以是n+2位(高两位始终为0) const bool y0 = Y ; // y0是Y的符号位 bitset<n> C = Y.to_ullong(); //截断符号位,C是乘数的绝对值(最后是积的低位) int cd = n; // cd是计数器 #pragma region 核心算法 while (cd--) { if (C[0]) { A = A + B; // 算术加 } RightMove(A, C); // A,C联合右移 } A = x0 ^ y0; #pragma endregion 核心算法 bitset<2 * n + 1> tmp(A.to_string().substr(1) + C.to_string()); return tmp; // 不能直接return!Shit!没有相应的复制构造函数? } bitset<2 * n + 1> DirectMul(const bitset<n + 1> X, const bitset<n + 1> Y) { const bitset<n> x(X.to_ullong()); const bitset<n> y(Y.to_ullong()); bitset<2 * n + 1> ans(x.to_ullong() * y.to_ullong()); ans[2 * n] = X ^ Y ; return ans; } int main(int argc, char **argv) { string inputStrX; string inputStrY; while (cin >> inputStrX >> inputStrY) { const bitset<n + 1> X(inputStrX); // X是被乘数 const bitset<n + 1> Y(inputStrY); // Y是乘数 cout << "TrueformOneMul:\t" << X << " * " << Y << " = " << TrueformOneMul(X, Y) << endl; cout << "DirectMul:\t" << X << " * " << Y << " = " << DirectMul(X, Y) << endl << endl; } return 0; }
输出:
相关文章推荐
- C++实现原码一位乘
- C++实现原码一位乘
- 一种定点原码一位乘法器的设计与实现
- C++实现原码一位乘
- C++实现原码一位乘,计组上机题
- 定点乘法运算之原码一位乘法
- C++实现——大数乘以小数
- 定点小数补码一位乘(校正法)
- 如何在C++中实现对输入数是否为小数的判断
- C++实现round四舍五入四位小数,类似C#的round函数
- 第九周(11.11-11.17)----结对项目----实现保留一位小数
- Android Edittext输入限制一位小数2位小数(n位)小数简单通用实现
- c++ 如何实现保留小数并 且 不进行四舍五入
- 定点乘法运算之原码一位乘法
- 使用C++中string实现任意长度的正小数、整数之间加减法方法实例
- C++ 实现IDL原码研究
- 定点乘法运算之原码一位乘法
- 深度学习FPGA实现基础知识20(FPGA小数运算--DSP基础“定点小数运算”)
- java实现两个整数相除保留一位小数
- 定点乘法运算之原码一位乘法