如果这就是您所需要的,那么实现起来并不难,特别是如果您愿意使用 Objective-C++。通过使用Objective-C++,你可以使用avector
来管理内存,从而简化了代码。
这是我们将要实现的接口:
// NSString+BigDecimalToHex.h
@interface NSString (BigDecimalToHex)
- (NSString *)hexStringFromDecimalString;
@end
为了实现它,我们将一个任意精度的非负整数表示为 base-65536 位的向量:
// NSString+BigDecimalToHex.mm
#import "NSString+BigDecimalToHex.h"
#import <vector>
// index 0 is the least significant digit
typedef std::vector<uint16_t> BigInt;
“困难”部分是将 a 乘以BigInt
10 并添加一个十进制数字。我们可以很容易地通过预加载进位的长乘法来实现这一点:
static void insertDecimalDigit(BigInt &b, uint16_t decimalDigit) {
uint32_t carry = decimalDigit;
for (size_t i = 0; i < b.size(); ++i) {
uint32_t product = b[i] * (uint32_t)10 + carry;
b[i] = (uint16_t)product;
carry = product >> 16;
}
if (carry > 0) {
b.push_back(carry);
}
}
有了这个辅助方法,我们就可以实现接口了。首先,我们需要BigInt
为每个十进制数字调用一次帮助方法,将十进制数字字符串转换为 a:
- (NSString *)hexStringFromDecimalString {
NSUInteger length = self.length;
unichar decimalCharacters[length];
[self getCharacters:decimalCharacters range:NSMakeRange(0, length)];
BigInt b;
for (NSUInteger i = 0; i < length; ++i) {
insertDecimalDigit(b, decimalCharacters[i] - '0');
}
如果输入字符串为空或全为零,b
则为空。我们需要检查一下:
if (b.size() == 0) {
return @"0";
}
现在我们需要转换b
为十六进制数字字符串。的最高有效数字b
位于最高索引处。为避免前导零,我们将特别处理该数字:
NSMutableString *hexString = [NSMutableString stringWithFormat:@"%X", b.back()];
然后我们将每个剩余的 base-65536 数字转换为四个十六进制数字,按照从最高有效到最低有效的顺序:
for (ssize_t i = b.size() - 2; i >= 0; --i) {
[hexString appendFormat:@"%04X", b[i]];
}
然后我们就完成了:
return hexString;
}
你可以在这个 gist中找到我的完整测试程序(作为 Mac 命令行程序运行)。