Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么std::bit_width为值0返回0,不应';它不是返回1吗?_C++_C++20 - Fatal编程技术网

C++ 为什么std::bit_width为值0返回0,不应';它不是返回1吗?

C++ 为什么std::bit_width为值0返回0,不应';它不是返回1吗?,c++,c++20,C++,C++20,std::bit_width查找表示整数xas1+floor(log(x)) 为什么std::bit_width为值0返回0?它不应该返回1吗,因为表示0所需的位数是1 此外,我认为公式中的1是一个偏移量。位宽度有一段奇怪的历史 最终被称为bit_width的函数作为提案的一部分,从log2开始使用日志2被指定在传递0时生成UB 因为对数就是这样工作的 但后来,情况发生了变化。该函数后来成为 Log2P1,并且(C++语句中的“宽合同”意味着更多的东西被认为是有效的输入)。具体来说,0是有效输入

std::bit_width
查找表示整数
x
as
1+floor(log(x))

为什么
std::bit_width
为值0返回0?它不应该返回1吗,因为表示0所需的位数是1


此外,我认为公式中的
1
是一个偏移量。

位宽度
有一段奇怪的历史

最终被称为
bit_width
的函数作为提案的一部分,从
log2
开始使用<代码>日志2
被指定在传递0时生成UB

因为对数就是这样工作的

但后来,情况发生了变化。该函数后来成为 Log2P1,并且(C++语句中的“宽合同”意味着更多的东西被认为是有效的输入)。具体来说,0是有效输入,并产生0的值

这不是对数的工作原理,但不管怎样

随着C++20接近标准化,一个。名称log2p1恰好与IEEE-754算法的名称相对应,但这是一个完全不同的名称。此外,具有类似输入和结果的其他语言中的函数使用类似于
位长度的名称。就这样

因为它不再假装做对数了,所以0的行为可以是我们想要的任何东西


的确。前导零不被视为位长度的一部分,并且由于
0
的值包含所有前导零…

,因为它在数学上有意义:

bit_width(x) = log2(round_up_to_nearest_integer_power_of_2(x + 1))
bit_width(0) = log2(round_up_to_nearest_integer_power_of_2(0 + 1))
             = log2(1)
             = 0

要详细说明评论中所说的话:

假设“位宽度”表示“存储(非负整数)数字所需的最少位数”。直观地说,我们至少需要
log2(n)
位取整,所以这是一个接近
ceil(log2(n))
的公式,所以255将需要
ceil(log2(255))=ceil(7.99..=8位
位,但这对2的幂不起作用,所以我们可以在
n
中添加一个模糊因子来获得
ceil(log2(n+1))
。这恰好在数学上等同于正数n的
1+floor(log2(n))
,但是
log2(0)
在floor版本中没有定义或定义为像负数无穷大这样无用的东西

如果我们使用0的上限公式,我们会得到结果。你也可以看到我没有写出前导零,正如Nicol Bolas指出的,0都是前导零

N 垃圾箱(n) 位宽(n) 8. 1000 4. 7. 111 3. 6. 110 3. 5. 101 3. 4. 100 3. 3. 11 2. 2. 10 2. 1. 1. 1. 0 0
标准明确指定了这种行为,但没有给出任何动机。为什么它应该返回1?如果你想拿零个苹果,你需要零个篮子,不是吗?因此,例如,如果将数据存储为长度和指向可变长度缓冲区的指针,甚至不必使用任何缓冲区来表示零,因为开始时的长度为零。从另一个角度来看,这也是合乎逻辑的:它返回从右侧开始的最高值1位的位置,从1开始,所以0表示根本没有1位。或者,从另一个角度来看:2^0=1,因此一个0位长的数字可以正好代表一个状态:零。因此,零位足以表示数字零。@rohitt:是的,您需要长度零,但这与必须存储长度或提前知道最大可能长度没有区别。如果你想表示数字5,你需要3位,但是你还需要记住你需要3位,否则你无法区分数字5和一个更大的数字,当它们出现在比特流中时,包括更多的位。对于零也没什么不同,你需要0位来存储它,但是你仍然需要存储或者记住你需要读/写多少,在这种情况下什么都不需要。我们不需要一个数字来表示零。只有在人类可读的句子中,我们需要检测数字的存在,才需要使用一位数字表示零。否则,当我们已经知道那里有一个数字时,空的数字序列是零的完美表示,这也是更规则的。尝试编写一个算法,将自然值转换为可变长度的位字符串,反之亦然:如果我们将零表示为空字符串,则更容易。事实上,当我们需要一位数字零时,我们需要实现一个特殊的情况。非常小的诡辩,但我认为说“当超过0时UB…因为对数就是这样工作的”并不准确。UB的意思是“可以做任何事情,包括在函数返回值之外产生影响”。特别是,较新规范的行为与较旧规范100%兼容,因为“返回0”是UB的一个完全有效的实现。@psmears:“包括超出此函数返回值的效果”,这也是取0的对数时发生的情况。这是一件你不能做的事情,如果你做了,那么你的数学就被打破了,不再是真正的数学。在数学中,包含加减无穷大,并将log0定义为负无穷大是完全有效的(也是有用的)。或者将日志视为reals上的。这个答案现在说“这不是对数的工作方式”,关于一个行为,它100%符合你所描述的“这就是对数的工作方式”,这似乎有点不一致:)@psmears那么,以前称为
log2p1
的函数的工作原理与对数完全相同;问题是它计算的公式不是
floor(log(n)+1)
,而是
ceil(log(n+1))
。为什么委员会没有用第二个公式来描述它,它适用于所有的<代码> N>代码>,而是使用了第一个在代码< n=0 < /COD>中有尴尬的不连续性,因此需要更详细地描述,这是任何人的猜测(毕竟是我们所讨论的C++标准委员会)。