将非常大的十进制字符串转换为十六

时间:2013-03-13 20:14:17

标签: objective-c

我在NSString中有一个非常大的十进制数,它太大而无法容纳任何变量,包括NSDecimal。我手动进行数学运算,但是如果我不能将数字拟合到变量中那么我就不能将它分开。那么转换字符串的好方法是什么?

输入示例:423723487924398723478243789243879243978234

输出:4DD361F5A772159224CE9EB0C215D2915FA

我正在查看第一个答案here,但它在C#中,我不知道它的客观C等价。

有没有人有任何不涉及使用外部库的想法?

1 个答案:

答案 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