Ios Objective-C中的Base 62转换

Ios Objective-C中的Base 62转换,ios,objective-c,cocoa-touch,Ios,Objective C,Cocoa Touch,我花了太多时间试图找到Objective-C的base 62转换的实现。我确信这是一个糟糕的示例,必须有一种优雅、超高效的方法来实现这一点,但这很有效,请编辑或回答以改进它!但我想帮助人们寻找这一点,有一些将工作。对于Objective-C实现,似乎找不到任何特定的东西 @implementation Base62Converter +(int)decode:(NSString*)string { int num = 0; NSString * alphabet = @"012

我花了太多时间试图找到Objective-C的base 62转换的实现。我确信这是一个糟糕的示例,必须有一种优雅、超高效的方法来实现这一点,但这很有效,请编辑或回答以改进它!但我想帮助人们寻找这一点,有一些将工作。对于Objective-C实现,似乎找不到任何特定的东西

@implementation Base62Converter

+(int)decode:(NSString*)string
{
    int num = 0;
    NSString * alphabet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    for (int i = 0, len = [string length]; i < len; i++)
    {
        NSRange range = [alphabet rangeOfString:[string substringWithRange:NSMakeRange(i,1)]];
        num = num * 62 + range.location;
    }

    return num;
}

+(NSString*)encode:(int)num
{
    NSString * alphabet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    NSMutableString * precursor = [NSMutableString stringWithCapacity:3];

    while (num > 0)
    {
        [precursor appendString:[alphabet substringWithRange:NSMakeRange( num % 62, 1 )]];
        num /= 62;
    }

    // http://stackoverflow.com/questions/6720191/reverse-nsstring-text
    NSMutableString *reversedString = [NSMutableString stringWithCapacity:[precursor length]];

    [precursor enumerateSubstringsInRange:NSMakeRange(0,[precursor length])
                             options:(NSStringEnumerationReverse |NSStringEnumerationByComposedCharacterSequences)
                          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                              [reversedString appendString:substring];
                          }];
    return reversedString;
}

@end
@实现Base62Converter
+(int)解码:(NSString*)字符串
{
int num=0;
NSString*字母=@“0123456789ABCDEFGHIJKLMNOPQRSTUVXYZABCDFGHIJKLMNOPQRSTUVXYZ”;
for(int i=0,len=[字符串长度];i0)
{
[字符串:[字母表substringWithRange:NSMakeRange(num%62,1)];
num/=62;
}
// http://stackoverflow.com/questions/6720191/reverse-nsstring-text
NSMutableString*reversedString=[NSMutableString stringWithCapacity:[前置长度]];
[前体枚举子字符串范围:NSMakeRange(0,[前体长度])
选项:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences)
使用block:^(NSString*子字符串、NSRange substringRange、NSRange enclosuringrange、BOOL*停止){
[反向字符串appendString:子字符串];
}];
返回反向字符串;
}
@结束

您的代码很好。如果有的话,让它更通用。以下是任意基的递归版本(相同代码):

#导入
@接口BaseConversion:NSObject
+(NSString*)formatNumber:(nsInteger)n toBase:(nsInteger)base;
+(NSString*)formatNumber:(NSInteger)n使用alphabet:(NSString*)字母表;
@结束
@实现基转换
//使用字母表长度作为基准。
+(NSString*)格式编号:(NSInteger)n使用字母表:(NSString*)字母
{
NSU整数基=[字母长度];
如果(n=base,@“字符不够,请使用base%ld或更低的字符。”,(无符号长)[字母表长度];
return[使用alphabet:[字母表substringWithRange:NSMakeRange(0,base)]的自格式化编号:n];
}
@结束
int main(int argc,char*argv[]){
@自动释放池{
NSLog(@“%@,[BaseConversion formatNumber:3735928559 toBase:16]);//死牛肉
返回退出成功;
}
}

Swift 3版本:

您可以改进
编码方法,从而不必反转最终字符串:

+ (NSString *)encode:(NSUInteger)num
{
    NSString *alphabet = @"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSUInteger base = [alphabet length];
    NSMutableString *result = [NSMutableString string];
    while (num > 0) {
        NSString *digit = [alphabet substringWithRange:NSMakeRange(num % base, 1)];
        [result insertString:digit atIndex:0];
        num /= base;
    }
    return result;
}
当然,正如@Jano在他的回答中所建议的那样,这也可以推广到任意基数或字母表

请注意,此方法(以及原始代码<代码> <代码>方法)返回一个空字符串,用于<代码> num=0 < /COD>,因此您可能需要单独考虑这个情况(或者只是替换<代码>而(Num>0){…} /代码>按<代码> do{}……(Num>0)< /Cord>
为了提高效率,可以完全避免所有中间
NSString
对象,并使用普通C字符串:

+ (NSString *)encode:(NSUInteger)num
{
    static const char *alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSUInteger base = 62;

    char result[20]; // sufficient room to encode 2^64 in Base-62
    char *p = result + sizeof(result);

    *--p = 0; // NULL termination
    while (num > 0) {
        *--p = alphabet[num % base];
        num /= base;
    }
    return [NSString stringWithUTF8String:p];
}

我不熟悉base 62转换。它用于什么?用于生成长整数的短版本。你知道那些生成短URL的站点吗?它们将使用“1ly7vl”而不是“1234567891”.我刚刚意识到我使用的是
int
s,这将限制输入的大小,并会在某个数字以上产生不好的结果…将纠正(或有人击败我)因告诉我一些我从未听说过的事情而被高票否决的错误!当然是为了与人鬼混(假设您不关心与其他系统的互操作性),您只需要使用随机版本的字母表;-)我建议使用字母表@“0123456789abcdefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyz”。我这样说是因为大多数其他b62实现(最重要)使用此排序。我喜欢直接转换检查!智能。我建议将其命名为**
格式
***
编号:toBase:
。还有更通用的版本吗?这应该只是
格式编号:toBase:usingAlphabet:
:)的包装器甚至不需要给出基数——从字母表的长度推导出来。谢谢Josh和Hot Clicks,我添加了你的建议。如果您愿意,请随意编辑答案。
+ (NSString *)encode:(NSUInteger)num
{
    static const char *alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSUInteger base = 62;

    char result[20]; // sufficient room to encode 2^64 in Base-62
    char *p = result + sizeof(result);

    *--p = 0; // NULL termination
    while (num > 0) {
        *--p = alphabet[num % base];
        num /= base;
    }
    return [NSString stringWithUTF8String:p];
}