我一直使用流,printf,string(x)或所讨论的任何语言将数字类型转换为字符串或背面。但是,我从来没有真正考虑过这是如何实际完成的。我在Google上进行了搜索,但所有结果都是为了使用这些方法,而不是如何在幕后进行转换的方式:(

对于使用二进制的整数,八分和十六进制似乎很简单,因为字符串中的每个“数字”都代表一组零位(例如,我知道它的xxxxxyyyy),所以我可以做到这一点一次数字,例如,对于十六进制字符串0xfa20,值为“(15 << 12)|(10 << 8)|(2 << 4)|(0 << 0)”。

十进制整数更加困难,因为基本10不会像这样映射到基本2,因此一位可能会影响一个以上的小数数字,使转换两种方式更为复杂...

至于浮点数,我真的不知道。我猜整个部分和分数可以单独考虑吗?那是指数,一定数量的重要数字或小数位数的数量呢?

有帮助吗?

解决方案

十进制转换要慢一些,但实际上并不复杂得多。让我们看一下十六进制的转换,就像我们可能会用真实代码编写它一样。例如,在C ++中,您可能会进行类似的转换:

char digits[] = "0123456789abcdef";
std::string result;

int input = 0xFA20;

while (input) {
    int digit = input & 0xf; // or: digit = input % 0xf;
    input >>= 4;             // or: input /= 16;
    result.push_front(digits[digit]);
}

但是,现在有一些魔术数字。让我们摆脱它们:

const int base = 16;

while (input) { 
    int digit = input % (base - 1);
    input /= base;
    result.push_front(digits[digit]);
}

在摆脱这些魔术数字的过程中,我们还将例行程序几乎通用 - 如果我们更改“基础”的值,则其余程序仍然有效,并将输入转换为指定的基础。从本质上讲,如果我们想支持大于16的基础,那么我们唯一需要做出的其他更改是将更多的“数字”数组添加到“数字”数组中。

为简单起见,这也忽略了一些事情。最明显的是,如果数字为负,则通常设置标志,转换为正数,最后,如果设置了标志,则将“ - ”放入字符串中)。使用2的补充,有一个最大负数数字的角案例,无法将其转换为正数(不转换为具有更多范围的类型)。通常,您可以通过推广大多数类型来处理。对于您最大的整数类型(您无法促进),通常最容易仅硬编码一个值。

原则上,浮点并没有大不相同 - 您基本上仍然进行数学操纵一次以一次生成一个数字。实际上,它变得更加复杂,仅仅是因为您通常必须处理几种不同的格式(至少是“基本”浮点和某种“科学”格式),以及用于场宽度和精度的变量。当您处理此问题时,您最终获得了几百行代码左右 - 不是特别令人发指的数量,但可能远远超出了这里的意义。

其他提示

我在Google上进行了搜索,但所有结果都是为了使用这些方法,而不是如何在幕后进行转换的方式:(

出于绩效原因,从一个表示形式转换为另一种表示(尤其是浮点/整数转换)通常是低级CPU指令,并在处理器级别实现。这就是为什么您通常不会在库中或语言级别重新完成它的原因。

例如,在信号处理世界中,这尤其常见,例如,您想在某些范围内将波形转换为离散的整数值。

对于整数您可以找到剩余的划分,这是最后一位,除以10,发现模块化残差 - 这是最后一个数字,依此类推。浮点数是由两个部分构建的 - 重要数字和指数,即=显着。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top