我目前正在研究一个概念,并且在问这个问题时正在编写伪代码。我正在考虑制作一个相当简单易用的类接口来表示 BigInts。我正在考虑制作几个具有 BigInt 类将使用的基本属性和成员的简单结构。例如,它不是直接处理负值的 BigInt 类,而是包含一个 Sign 结构,并且这个结构基本上包含一个值 0 或 1,或者基本上是一个布尔类型来指定这个 BigInt 是正数还是负数。在构建时,我打算让该类默认生成一个正数。我还想有一个结构来表示有两个变体的数字。第一个变体具有数字 0-9,第二个变体将继承原始变体但也包括 AF。这样,作为模板类但只有两种有效类型的类将支持十进制和十六进制的使用。所有数学运算符都将在类之外定义,并且根据其推断类型,它将调用并执行适当版本的函数。然而,十六进制部分仍然只是概念,因为我想首先启动并运行十进制版本。这些帮助类可能看起来像这样:希望首先启动并运行十进制版本。这些帮助类可能看起来像这样:希望首先启动并运行十进制版本。这些帮助类可能看起来像这样:
class Sign {
private:
bool isNegative_ { false };
char sign_;
public:
Sign() : isNegative_( false ) {
sign_ = '+';
}
Sign( const bool isNegative ) : isNegative_( isNegative ) {
sign_ = isNegative_ ? '-' : '+';
};
Sign( const char sign ) {
if ( sign == '+' || sign == '\0' || sign == ' ' ) {
isNegative_ = false;
} else if ( sign == '-' ) {
isNegative_ = true;
} else {
// throw error improper character.
}
}
bool isPostive() const { return !isNegative_; }
bool isNegative() const { return !isNegative; }
char sign() const { return sign_; }
char negate() {
isNegative_ = !isNegative_;
sign_ = isNegative_ ? '+' : '-';
return sign_;
}
};
// NST = NumberSystemType
class enum NST { Decimal = 10, Hexadecimal = 16 };
template<class NT> // NT = NumberType
class Digit {
private:
NST nst_; // determines if Decimal or Hexadecimal
};
// Specialization for Decimal
template<NST::Decimal> // Should be same as template<10>
class Digit {
// would like some way to define 4 bits to represent 0-9; prefer not to
// use bitfields, but I think a char or unsigned char would be wasting
// memory using twice as much for what is needed. Not sure what to do here...
// maybe std::bitset<>...
};
template<NST::Hexadecimal> // Should be same as template<16>
class Digit : public Digit<Decimal> { // Also inherits all of The first specialization.
// same as above only needs 4 bits to represent values form 0-F
// A half char would be excellent but does not exist in c++... and most
// programming language's types.
// still thinking of maybe std::bitset<>...
};
两者之间的主要区别在于,第一个特化只允许 0-9 的数字值和 0-9 的数字本身,而第二个没有该限制,但也允许从 af 和或 AF 任何一种情况都有效。我还可以包含一个 const char* 来指定0x
将附加到任何包含的值以进行显示的十六进制前缀。
我喜欢这种设计方法,因为我想将 BigInt 类的实际算术函数和运算符保留为单独的函数模板,因为 BigInt 类可以支持 Decimal 和 Hexadecimal 专用模板类型。如果一切顺利,我还想添加支持以使用复数。
BigInt 类将是这样的:
template<class NT>
BigInt {
private:
Sign sign_;
Digit<NT> carryDigit_;
std::vector<Digit<NT>> value_;
// May contain some functions such as setters and getters only
// Do not want the class to be modifying itself except for assignment only.
};
如上所述,这也适用于十进制和十六进制类型,但是如果有人创建了 BigInt<> myBigInt 的实例,则默认为十进制!
对于向量中包含的数据。我想以与阅读内容相反的顺序存储数字。因此,如果它们是345698
BigInt 内部向量中的一个数字,它将存储为896543
. 这样做的原因是,当我们在数学中进行算术运算时,我们从小数点左侧的右侧开始从最低有效位到最高有效位,这是无关紧要的,因为这是一个仅限 BigInt 的类,我们以自己的方式工作左边。但是,如果我们以正确的顺序在上述类的向量的每个元素中存储每个只能是 0-9 的数字,并且我们使用外部 operator+() 函数,这对于一个 BigInt 到另一个来说将是具有挑战性的......例如:
Basic Arithmetic R - L | Vector storing standard
12345 <1,2,3,4,5>
+ 678 <6,7,8>
------
13023
这里 <5> 和 <8> 的索引不重合,所以这使得很难弄清楚如何将一个有几个数字的值添加到一个有多个数字的值。我的方法是,如果我们以相反的顺序存储数字:
| Vector stored in reverse
<5,4,3,2,1>
<6,7,8>
那么加法就变得简单了!我们所要做的就是将 BigInt 的两个向量中的每个数字加上相同的索引值。我们可以使用进位数字来结转到下一个字段。生成的 BigInt 返回的大小至少等于或大于两个 BigInt 中最大的一个。如果 carryDigit 有一个值,那么下一次迭代的加法运算将包括 3 个加法而不是 2 个。现在,当获取 BigInt 进行显示时,我们可以返回一个向量>,除了当用户获取它时,这不是“BigInt”,它是数字向量,并且它的顺序也是正确的。它甚至可以通过字符串表示形式返回。这个类可以由一个vector>构造,它在内部存储时会颠倒顺序。
这是我的 BigInt 类的总体概念,我只是想知道这是否是一个好的设计计划,是否会被认为是有效的,我想我的主要问题是关于使用什么来存储实际数字Digit 的类...是否适合保存内存占用空间,或者使用 a而不用担心额外的空间std::bitset<>
会更好,因为 pro 更易于实现?char