2012-07-05 82 views
8
myInt = int(5 * myRandom()) 

myRandom()是随机生成的浮动,这是0.2。铸造为int和浮点错误?

因此,此声明应评估为1

我的问题:是否可能由于浮点错误而不会评估为1

例如,如果由于浮点错误的东西应该是0.2会是比LESS? IE,例如考虑以下3种可能性:

int(5 * 0.2)    = 1 //case 1 normal 
int(5 * 0.2000000000000001) = 1 //case 2 slightly larger, its OK 
int(5 * 0.1999999999999999) = 0 //case 3 negative, is NOT OK, as int() floors it 

情形3甚至有可能?与0.1999999999999999是一个浮点错误的结果?到目前为止,我从来没有见过一个负ε,只有情况2,当它稍微大一点时,并且没问题,就像当它投射到int()时一样,它会将其“落地”到正确的结果。然而,如果是负ε,“地板”效应将使得0.9999999999999996的结果为0.

+0

我不认为这是可能的,不。乘法和舍入只应该注意可能的有效数字的最大数目。 – Ryan 2012-07-05 19:15:48

+1

如果它是随机生成的,为什么“应该”是0.2? – 2012-07-05 19:19:52

+0

这是C++,而不是C.您不能在C. – 2012-07-05 19:20:02

回答

3

myRandom不可能返回.2因为.2不能表示为float或double,假设您的目标系统使用IEEE 754二进制浮点标准,这绝对是默认值。

如果myRandom()返回最接近0.2的可表示数,那么myInt将为1,因为最接近.2的数可表示为浮点数,它略大于.2(它是0.20000000298023223876953125),因此是最接近的可表示形式双倍(0.20000000000000001110223024625156540423631668090820312)。

在其他情况下,这不是事实。例如,与.6最接近的两倍是0.59999999999999997779553950749686919152736663818359375,所以myInt将是2,而不是3.

+0

我喜欢你的答案最好,但它是令人担忧的。真正的问题是,如果我能通过将一个float赋给一个int来得到一个确定的结果,然而从你对0.6的说法来看,它似乎没有。我将需要做一些自定义四舍五入。 – 2012-07-05 20:43:09

1

是的,至少就C标准而言是可能的。

0.2不能完全用二进制浮点格式表示。因此,myRandom()返回的值将略低于或略高于数学值0.2。 C标准允许任一结果。

现在很可能IEEE语义只允许结果略大于0.2--但C标准不要求IEEE语义。假设结果是从值0.2尽可能精确地推导出来的。如果该值是由一系列浮点运算生成的,其中每个浮点运算都可能引入一个小错误,则它可能很容易小于或大于0.2

+0

作为一个附录,将一个float浮点数转换为一个int,所以如果该值稍大于0.2,那么最终的结果是一个稍大于1的产品,它会向下舍入。 – Wug 2012-07-05 19:21:07

+0

这只是一个例子,myRandom()可以是从0到1的任何值,但0.2似乎是一个很好的例子来说明0和1的结果之间的差异。真正的问题是关于决定论,我期望找出如果将Floatpoint强制转换为int,会导致确定性结果。它看起来不像。 – 2012-07-05 20:39:26

1

这不是浮点数错误,这是浮点运算的方式。任何不是1 /(2的幂)的分数不能精确表示,并且将向上舍入或者向下舍入至最接近的可表示数。

在转换为整数之前,您可以通过乘以一个大于1的小epsilon来修复您的代码。

myInt = int(5 * myRandom() * 1.000000000000001) 

参见What Every Computer Scientist Should Know About Floating-Point Arithmetic

0

这可能取决于您选择的数量。 要检查一个特定的数字,你总是可以用很高的精度打印它们:printf(“%1.50f”,0.2)

0

为什么不把你的float乘以5.0然后使用round函数来正确地舍入它?

+0

这是一个例子,这些不是实际的数字。 – 2012-07-05 20:38:11

+0

这个想法仍然有效。 – 2012-07-05 23:20:48