これだけあれば、特に Objective-C++ を使用したい場合は、実装するのはそれほど難しくありません。Objective-C++ を使用すると、 を使用しvector
てメモリを管理できるため、コードが簡素化されます。
実装するインターフェイスは次のとおりです。
// NSString+BigDecimalToHex.h
@interface NSString (BigDecimalToHex)
- (NSString *)hexStringFromDecimalString;
@end
それを実装するために、任意精度の負でない整数を基数 65536 の数字のベクトルとして表します。
// NSString+BigDecimalToHex.mm
#import "NSString+BigDecimalToHex.h"
#import <vector>
// index 0 is the least significant digit
typedef std::vector<uint16_t> BigInt;
「難しい」部分は、aBigInt
に 10 を掛けて、それに 10 進数を 1 桁追加することです。これは、プリロードされたキャリーを使用した長い乗算として非常に簡単に実装できます。
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
まず、10進数ごとにヘルパー メソッドを 1 回呼び出して、10 進数の文字列を に変換する必要があります。
- (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
次に、16 進数の文字列に変換する必要があります。の最上位桁b
は、最高のインデックスにあります。先行ゼロを避けるために、その桁を特別に処理します。
NSMutableString *hexString = [NSMutableString stringWithFormat:@"%X", b.back()];
次に、残りの base-65536 の各数字を、最上位から最下位の順に 4 つの 16 進数に変換します。
for (ssize_t i = b.size() - 2; i >= 0; --i) {
[hexString appendFormat:@"%04X", b[i]];
}
これで完了です。
return hexString;
}
私の完全なテスト プログラム (Mac コマンド ライン プログラムとして実行する)は、この gist にあります。