我在NSString中有一个非常大的十进制数,它太大而无法容纳任何变量,包括NSDecimal。我手动进行数学运算,但是如果我不能将数字拟合到变量中那么我就不能将它分开。那么转换字符串的好方法是什么?
输入示例:423723487924398723478243789243879243978234
输出:4DD361F5A772159224CE9EB0C215D2915FA
我正在查看第一个答案here,但它在C#中,我不知道它的客观C等价。
有没有人有任何不涉及使用外部库的想法?
答案 0 :(得分:1)
如果这就是您所需要的,那么实现起来并不难,特别是如果您愿意使用Objective-C ++。通过使用Objective-C ++,您可以使用vector
来管理内存,从而简化代码。
这是我们要实现的界面:
// 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;
“硬”部分是将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
:
- (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()];
然后我们将每个剩余的基数-65536数字转换为四个十六进制数字,从最重要到最不重要的顺序:
for (ssize_t i = b.size() - 2; i >= 0; --i) {
[hexString appendFormat:@"%04X", b[i]];
}
然后我们就完成了:
return hexString;
}
您可以找到我的完整测试程序(作为Mac命令行程序运行)in this gist。