正如我解释它, MSDN的定义的numeric_limits::is_exact
几乎都是假的:
[全部]在[这里]类型来完成的计算是免费的舍入误差。
而IBM的定义几乎总是正确的:(或圆形的定义,这取决于你怎么看它)
具有用于其所有值确切表示一个类型
有什么我可以肯定的是,我可以一个存储2
两一个double
和一个long
,他们都希望能准确表示。
我可以再由他们分开两个10
也不准确将持有的数学结果。
由于任何数字数据类型T
,什么是确定正确的方法std::numeric_limits<T>::is_exact
?
编辑:我已经发布了什么,我认为是一个准确的答案 ,从许多的答案提供的细节这个问题。 这个答案是不是赏金的有力竞争者 。
在标准(见NPE的答案)的定义是不是非常精确,是吗? 相反,它是圆形的和模糊的。
鉴于IEC浮点标准具有“不精确”号的概念(当计算获得精确的数字不精确异常),我怀疑这是名字的由来is_exact
。 需要注意的是标准类型的, is_exact
仅是假的float
, double
,和long double
。
这样做的目的是指示类型是否正好代表了所有基本的数学式的数字。 对于整型,基本的数学式是整数的一些有限子集。 由于每个整型正好代表了该类型有针对性的整数的子集的成员的每一个, is_exact
是所有整数类型也是如此。 对于浮点类型,基本的数学式是实数的一些有限范围的子集。 (有限范围的子集的一个例子是“0和1之间的所有实数”。)没有办法甚至表示完全实数的有限范围子集; 几乎所有的都是不可计算。 在IEC / IEEE格式使事情变得更糟。 与该格式,电脑甚至不能代表有理数的有限范围的子集恰好(更不用说可计算数的有限范围的子集)。
我怀疑这个词的起源is_exact
是在不同的浮点表示模型“不精确”号的长期概念。 也许是一个更好的名字会一直is_complete
。
附录
由语言定义的数字类型不是BE全部和最终所有“数字”的表示。 甲定点表示本质上是整数,因此他们也将是精确的(在表示没有孔)。 表示有理数作为一对标准积分类型的(例如, int/int
)就不会是精确的,但其表示的有理数作为一类Bignum
对将,至少在理论上,是“精确”。
怎么样的实数? 有没有办法准确地表示实数,因为几乎所有的实数是不可计算的。 我们可以可能与电脑做的最好的是可计算的数字。 这就需要代表一个数字作为某种算法。 虽然这可能是有用的理论,从实际情况来看,这是没有多大用处的根本。
第二个增补
开始的地方是与标准。 两个C ++ 03和C ++ 11限定is_exact
为
如果类型使用的确切表示真。
这既是模糊和循环。 这是毫无意义的。 没有这么毫无意义的是整数类型( char
, short
, int
, long
,等等)是“精确”菲亚特:
所有整数类型是准确的,...
那么其他的算术类型? 首先要注意的事情是,唯一的其他算术类型的浮点类型float
, double
,和long double
(3.9.1 / 8):
有三种浮点类型: float
, double
,和long double
。 ...浮点类型的值表示是实现定义的。 整型和浮点型,统称算术类型。
在C ++中的浮点类型的意义是明显的模糊。 与Fortran的比较:
一个真正的数据是一个处理器近似为实数的值。
符合ISO / IEC 10967-1,语言独立的算法(在脚注其中C ++标准参考,但从来没有作为规范参考)比较:
浮点F型应ℝ的有限子集。
C ++,另一方面是没有实际意义对于什么浮点类型应该代表。 据我所知,一个实现可以逃脱制作float
的代名词int
, double
的代名词long
和long double
的代名词long long
。
再次从标准is_exact
:
......但不是所有的确切类型是整数。 例如,理性和固定指数表示是准确的,但不是整数。
这显然不适用于用户开发的扩展原因很简单,不允许用户定义std::whatever<MyType>
。 做到这一点,你调用未定义的行为。 这最后一句只能属于实现,
- 定义
float
, double
,和long double
在一些特殊的方式,或 - 提供一些非标准理性或固定点类型作为算术类型,并决定提供
std::numeric_limits<non_standard_type>
对于这些非标准扩展。
我建议is_exact是真的当且仅当该类型的所有文字都有其确切价值。 所以is_exact是浮动类型的假的,因为字面0.1的值是不完全的0.1。
每基督教劳的评论,我们可以改为定义is_exact当四个运算的类型的任何两个值之间的结果要么是超出范围或可精确表示是真实的,使用操作的定义为类型(即,截断的整数除法,无符号环绕)。 根据这个定义,你可以吹毛求疵浮点运算被定义为产生最接近的可表示值。 别 :-)
exactnes的问题并不仅限于C,所以让我们看得更远。
大约相隔标准节录锗dicussion,不精确必须适用于需要四舍五入为表示与同类型的结果的数学运算。 例如,方案有这样那样精确/不精确的定义,通过精确的操作和准确的字面常量的平均值看R5RS§6。 从标准程序http://www.schemers.org/Documents/Standards/R5RS/HTML
为的情况下, double x=0.1
,我们要么认为0.1是良好限定的双文字,或如方案,该文字是由一个不精确的编译时操作形成一个不精确的常数(四舍五入至操作的最近双结果1 / 10,它在Q中很好定义的)。 所以,我们总是最终的操作。
让我们专心+,别人可以用数学+的均值和组属性定义。
然后不精确的可能定义是:
If there exists any pair of values (a,b) of a type such that a+b-a-b != 0,
then this type is inexact (in the sense that + operation is inexact).
对于每一个浮点表示,我们知道的(南琐碎的情况下和INF分开)有明显存在这样的对,所以我们可以告诉大家,浮动(操作)是不准确的。
对于明确限定的无符号算术模型,+是准确的。
对于有符号整数,我们有UB的溢出的情况下这个问题,所以没有精确的保修......除非我们完善规则,以应付这个破碎的算法模型:
If there exists any pair (a,b) such that (a+b) is well defined
and a+b-a-b != 0,
then the + operation is inexact.
远高于definedness可以帮助我们扩展到其他操作为好,但它是不是真的有必要。
然后,我们就不得不考虑/假多态性的情况下,而不是不精确
(/被定义为欧几里得除法的商为INT)。
当然,这不是一个官方的规则,这个答案的有效性是有限的理性思维的努力
在C ++标准中给出的定义似乎相当明确的:
static constexpr bool is_exact;
如果类型使用的确切表示真。 所有整数类型是精确的,但不是所有的确切类型是整数。 例如,理性和固定成本,指数表示是准确的,但不是整数。
有意义的所有专业。
在C ++中int类型用于表示某个整数类型(即该组中的一个{...,-1,0,1,...})。 由于实现的实际限制,语言定义的值的最小范围 ,应该由该类型举行,并在该范围内的所有有效的值必须在没有上所有已知的架构含糊表示。
该标准还定义了用于保存浮点数类型,每个都有自己的有效值范围。 什么,你不会找到有效浮点数的列表。 此外,由于实际限制在标准允许这些类型的近似值。 很多人试图说,仅可以由IEEE浮点标准来表示数字是这些类型的精确值,但是这不是标准的一部分。 虽然这是事实,在二进制计算机语言的实现关系到如何双和浮子代表的标准,有没有在说,它必须是一个二进制的计算机上实现的语言。 换句话说浮子不是由IEEE标准定义,IEEE标准仅仅是一个可接受的实施。 因此,如果有可能的,如果没有四舍五入规则或估计定义双和浮点值的范围内持有任何价值的实现,你可以说,is_exact在该平台如此。
严格地说,T不能成为你告诉是否型“is_exact”,但我们可以推断一些其他参数唯一的参数。 因为你可能使用与标准的硬件和任何可公开获得的C ++编译器,当你指定的.1双重价值(这是在可接受的范围浮点类型)的二进制计算机,这不是数字电脑会在与该变量计算使用。 它使用由IEEE标准所定义的最接近。 当然,如果你比较文字与自己的编译器应该返回true,因为IEEE标准是非常明确的。 我们知道,计算机不具有无限的精度,因此,我们期望有.1值不一定会与文字值具有相同的近似表示最终的计算。 进入可怕的小量的比较。
为切实回答你的问题,我要说的是,对于任何类型的需要小量的比较来测试近似相等,is_exact应该返回false。 如果严格比较是足够的那种类型,它应该返回true。
std::numeric_limits<T>::is_exact
应该false
当且仅当T
的定义允许可能是不可存储的值。
C ++认为任何浮点字面成为它的类型的有效值。 而允许实现决定了哪些值精确存储的表示。
因此,对于在允许的范围内(例如每实数2.0
或0.2
),C ++ 总是许诺的数量是有效的double
和从未承诺该值可以精确地储存。
这意味着,两个假设的问题让-而真正的无处不在的IEEE浮点标准-是不正确的C ++定义:
我敢肯定,我可以存储2
在双完全相同。
然后,我可以通过划分[它] 10
号和[那双不会 ] 恰好持有的数学结果。