为什么在这段代码中使用 log base 10 将 int 转换为 string?
Why is log base 10 used in this code to convert int to string?
我看到 post 解释了如何将 int 转换为字符串。在解释中有一行代码可以获取字符串中的字符数:
(int)((ceil(log10(num))+1)*sizeof(char))
我想知道为什么使用 log base 10?
这是因为它分配的 space 足以让数字适合字符串。
例如,如果您的号码是 1034,log10(1034) = 3.0145...
。 ceil(3.0145)
是4,也就是数字的位数。 + 1
用于空终止符。
但这并不完美:以 1000 为例。尽管有四位数字,log(1000) = 3
和 ceil(3) = 3
,所以这将为太少的数字分配 space。另外,正如@phuclv 在下面提到的,log()
函数为此目的非常耗时,尤其是因为数字的长度有一个(相对较低的)上限。
它以 10 为底的对数的原因是,大概是因为此函数表示十进制形式的数字。例如,如果它是十六进制的,将使用以 16 为底的日志。
ceil(log10(num))+1
被错误地使用而不是 floor(log10(num))+2
.
代码正在尝试确定将正整数 num
的十进制表示形式存储为字符串所需的内存量。
上面给出的两个公式除了数字是 10 的精确幂之外是相等的,在这种情况下,前一个版本 return 比所需数字小一。
例如,10,000 需要 6 个字节,但 ceil(log10(10000))+1
returns 5
。 floor(log10(10000))+2
正确 returns 6.
floor(log10(num))+2
是怎么得到的?
4位数字如4567会在1000(含)到10000(不含)之间,所以它会在103(含)到10[=之间40=]4(不含),所以log10(4567)会在3(含)和4(不含)之间。
因此,floor(log10(num))+1
将 return 表示十进制正值 num
所需的位数。
因此,floor(log10(num))+2
将 return 将正整数 num
的十进制表示形式存储为字符串所需的内存量。 (额外的字符用于终止字符串的 NUL。)
ceil(log10(num)) + 1 旨在提供输出字符串所需的字符数。
例如,如果 num=101,则表达式的值为 4,即“101”的正确长度加上空终止符。
但如果 num=100,则值为 3。此行为是不正确的。
数字 N
有 n 个十进制数字当且仅当 10^(n-1) <= N < 10^n
等于 n-1 <= log(N) < n
或 n = floor(log(N)) + 1
.
由于 double
表示的精度有限 floor(log(N))
对于某些值可能会偏离 1,因此允许额外的数字更安全,即分配 floor(log(N)) + 2
个字符,并且然后是 nul 终止符的另一个字符,总共 floor(log(N)) + 3
.
原题ceil(log(N)) + 1
中的表达式似乎没有计算nul终止符,也没有考虑到舍入误差的可能性,所以一般会短一个,10的幂则短两个。
I’m wondering why log base 10 is used?
我也在想同样的事情。它使用在运行时发生的 非常 复杂的计算,以节省几个字节的 临时 存储。而且它做错了。
原则上,您可以通过取以 10 为底的对数和 flooring 并加 1 来获得以 10 为底的位数。它正是来自
log10(1) = log10(10⁰) = 0
log10(10) = log10(10¹) = 1
log10(100) = log10(10²) = 2
10 到 100 之间的所有数字的对数都在 1 到 2 之间,所以如果你对任何两位数的对数求底,你会得到 1...加 1 就得到位数。
但您不需要在运行时执行此操作。以 10 为基数的 32 位 int 所需的最大字节数是 10 个数字、负号和 12 个字符的空终止符。通过运行时计算最多可以节省 10 字节 RAM,但这通常是临时的,因此不值得。如果它是堆栈内存,那么对 log10
、ceil
等的调用可能需要更多。
事实上,我们知道表示一个整数所需的最大位数:sizeof (int) * CHAR_BIT
。这大于或等于 MAX_INT + 1
的 log2。我们知道 log10(x)
=~ 3.32192809489 * log2(x)
,所以我们通过将 sizeof (int) * CHAR_BIT
除以 3 得到了 log10(MAX_INT)
的一个很好的(可能是最低限度的)近似值。然后加上 1
对于 我们应该在底对数上加 1 以获得位数 ,然后 1
表示可能的符号, 1
表示空终止符和我们得到
sizeof (int) * CHAR_BIT / 3 + 3
与你的问题不同,这是一个整数常量表达式,即编译器可以很容易地在编译时折叠它,它可以用来设置大小一个静态类型的数组,对于 32 位它给出 13 这只比实际需要的 12 多 1,对于 16 位它给出 8 这又只比所需的最大值多 7,对于 8 位,它给出 5 这是确切的最大值。
我看到 post 解释了如何将 int 转换为字符串。在解释中有一行代码可以获取字符串中的字符数:
(int)((ceil(log10(num))+1)*sizeof(char))
我想知道为什么使用 log base 10?
这是因为它分配的 space 足以让数字适合字符串。
例如,如果您的号码是 1034,log10(1034) = 3.0145...
。 ceil(3.0145)
是4,也就是数字的位数。 + 1
用于空终止符。
但这并不完美:以 1000 为例。尽管有四位数字,log(1000) = 3
和 ceil(3) = 3
,所以这将为太少的数字分配 space。另外,正如@phuclv 在下面提到的,log()
函数为此目的非常耗时,尤其是因为数字的长度有一个(相对较低的)上限。
它以 10 为底的对数的原因是,大概是因为此函数表示十进制形式的数字。例如,如果它是十六进制的,将使用以 16 为底的日志。
ceil(log10(num))+1
被错误地使用而不是 floor(log10(num))+2
.
代码正在尝试确定将正整数 num
的十进制表示形式存储为字符串所需的内存量。
上面给出的两个公式除了数字是 10 的精确幂之外是相等的,在这种情况下,前一个版本 return 比所需数字小一。
例如,10,000 需要 6 个字节,但 ceil(log10(10000))+1
returns 5
。 floor(log10(10000))+2
正确 returns 6.
floor(log10(num))+2
是怎么得到的?
4位数字如4567会在1000(含)到10000(不含)之间,所以它会在103(含)到10[=之间40=]4(不含),所以log10(4567)会在3(含)和4(不含)之间。
因此,floor(log10(num))+1
将 return 表示十进制正值 num
所需的位数。
因此,floor(log10(num))+2
将 return 将正整数 num
的十进制表示形式存储为字符串所需的内存量。 (额外的字符用于终止字符串的 NUL。)
ceil(log10(num)) + 1 旨在提供输出字符串所需的字符数。
例如,如果 num=101,则表达式的值为 4,即“101”的正确长度加上空终止符。
但如果 num=100,则值为 3。此行为是不正确的。
数字 N
有 n 个十进制数字当且仅当 10^(n-1) <= N < 10^n
等于 n-1 <= log(N) < n
或 n = floor(log(N)) + 1
.
由于 double
表示的精度有限 floor(log(N))
对于某些值可能会偏离 1,因此允许额外的数字更安全,即分配 floor(log(N)) + 2
个字符,并且然后是 nul 终止符的另一个字符,总共 floor(log(N)) + 3
.
原题ceil(log(N)) + 1
中的表达式似乎没有计算nul终止符,也没有考虑到舍入误差的可能性,所以一般会短一个,10的幂则短两个。
I’m wondering why log base 10 is used?
我也在想同样的事情。它使用在运行时发生的 非常 复杂的计算,以节省几个字节的 临时 存储。而且它做错了。
原则上,您可以通过取以 10 为底的对数和 flooring 并加 1 来获得以 10 为底的位数。它正是来自
log10(1) = log10(10⁰) = 0
log10(10) = log10(10¹) = 1
log10(100) = log10(10²) = 2
10 到 100 之间的所有数字的对数都在 1 到 2 之间,所以如果你对任何两位数的对数求底,你会得到 1...加 1 就得到位数。
但您不需要在运行时执行此操作。以 10 为基数的 32 位 int 所需的最大字节数是 10 个数字、负号和 12 个字符的空终止符。通过运行时计算最多可以节省 10 字节 RAM,但这通常是临时的,因此不值得。如果它是堆栈内存,那么对 log10
、ceil
等的调用可能需要更多。
事实上,我们知道表示一个整数所需的最大位数:sizeof (int) * CHAR_BIT
。这大于或等于 MAX_INT + 1
的 log2。我们知道 log10(x)
=~ 3.32192809489 * log2(x)
,所以我们通过将 sizeof (int) * CHAR_BIT
除以 3 得到了 log10(MAX_INT)
的一个很好的(可能是最低限度的)近似值。然后加上 1
对于 我们应该在底对数上加 1 以获得位数 ,然后 1
表示可能的符号, 1
表示空终止符和我们得到
sizeof (int) * CHAR_BIT / 3 + 3
与你的问题不同,这是一个整数常量表达式,即编译器可以很容易地在编译时折叠它,它可以用来设置大小一个静态类型的数组,对于 32 位它给出 13 这只比实际需要的 12 多 1,对于 16 位它给出 8 这又只比所需的最大值多 7,对于 8 位,它给出 5 这是确切的最大值。