浮点错误(更多信息) [英] Floating point error (more info)

查看:112
本文介绍了浮点错误(更多信息)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚发布了一个可能的浮点错误(不确定

在哪里),并且后来发现:


float f = 5.15002;

double d = 5.15002;

if(float(d)< f)

puts(" huh 1?");

float f2 = float(d);

if(f2< f)

puts(" huh 2?");

导致''huh 1''被打印,但不是''huh 2''。


我不知道这是否是编译器程序(MSVC 6),FPU问题或

什么!


汇编代码为:


6 :float f = 5.15002;

00401028 C7 45 FC F7 CC A4 40 mov dword ptr [ebp-4],40A4CCF7h

7:double d = 5.15002;

0040102F C7 45 F4 D2 FB C6 D7 mov dword ptr

[ebp-0Ch],0D7C6FBD2h

00401036 C7 45 F8 9E 99 14 40 mov dword ptr [ebp-8],4014999Eh

8:if(float(d)< f)

0040103D DD 45 F4 fld qword ptr [ebp-0Ch]

00401040 D9 55 EC fst dword ptr [ebp-14h]

00401043 D8 5D FC fcomp dword ptr [ebp-4]

00401046 DF E0 fnstsw ax
$ b $ 00 00401048 F6 C4 01测试啊,1

0040104B 74 0D je main + 4Ah(0040105a)

9:put(huh 1?);

0040104D 68 24 60 42 00推偏移字符串huh 1?

(00426024) )
$ b $ 00 00401052 E8 39 00 00 00看跌期权(00401090)

00401057 83 C4 04加esp,4

10:浮动f2 =浮动(d);

0040105A DD 45 F4 fld qword ptr [ebp-0Ch]

0040105D D9 5D F0 fstp dword ptr [ebp-10h]

11:if(f2< f)

00401060 D9 45 F0 fld dword ptr [ebp-10h]

00401063 D8 5D FC fcomp dword ptr [ebp-4]

00401066 DF E0 fnstsw ax
$ b $ 00 00401068 F6 C4 01测试啊,1

0040106B 74 0D je main + 6Ah(0040107a)

12:puts (huh 2?);

0040106D 68 1C 60 42 00推偏移字符串huh 2?

(0042601c)
$ b $ 00 00401072 E8 19 00 00 00看涨期权(00401090)

00401077 83 C4 04加esp,4

解决方案

通常,浮点数不能精确表示。


您可以通过在网上搜索IEEE来找到各种文本

使用您最喜爱的搜索引擎浮动指向。

其中一个可能有用的参考是:

http://msdn.microsoft.com/library/de .. .us / vccore / html

/ _core_why_floating_point_numbers_may_lose_precisio n.asp


如果您构建程序以进行调试,请逐步执行,然后查看记忆

内容

(实际的十六进制值,而不是转换后的基数10表示)是比较b / b
这可能会更清楚。


- joel

" Dylan Nicholson" < DP **** @ optushome.com.au>在消息中写道

news:73 ************************** @ posting.google.c om ...

我刚刚发布了一个可能的浮点错误(不确定
在哪里),并且发现了:

float f = 5.15002;
double d = 5.15002;
if(float(d)< f)
puts(huh 1?);
float f2 = float(d);
if(f2< f)
put(huh 2?);

导致''huh 1''被打印,但不是''huh 2''。

我不知道这是编译器程序(MSVC 6),FPU问题还是
什么!

汇编代码是:

6:浮点数f = 5.15002;
00401028 C7 45 FC F7 CC A4 40 mov dword ptr [ebp-4],40A4CCF7h
7:double d = 5.15002;
0040102F C7 45 F4 D2 FB C6 D7 mov dword ptr
[ebp-0Ch],0D7C6FBD2h
00401036 C7 45 F8 9E 99 14 40 mov dword ptr [ebp-8],4014999Eh
8: if(float(d)< f)
0040 103D DD 45 F4 fld qword ptr [ebp-0Ch]
00401040 D9 55 EC fst dword ptr [ebp-14h]
00401043 D8 5D FC fcomp dword ptr [ebp-4]
00401046 DF E0 fnstsw ax
00401048 F6 C4 01测试啊,1
0040104B 74 0D je main + 4Ah(0040105a)
9:puts(huh 1?);
0040104D 68 24 60 42 00推偏移字符串huh 1?
(00426024)
00401052 E8 39 00 00 00看涨期权(00401090)
00401057 83 C4 04 add esp,4
10:float f2 = float(d);
0040105A DD 45 F4 fld qword ptr [ebp-0Ch]
0040105D D9 5D F0 fstp dword ptr [ebp-10h]
11:if(f2< f)
00401060 D9 45 F0 fld dword ptr [ebp-10h]
00401063 D8 5D FC fcomp dword ptr [ebp-4]
00401066 DF E0 fnstsw ax
00401068 F6 C4 01测试啊,1 0/00 0010106B 74 0D je main + 6Ah(0040107a)
12:put(huh 2?);
0040106D 68 1C 60 42 00推偏移字符串" ;嗯2?"
(0042601c)
00401072 E8 19 00 00 00来电(00401090)
00401077 83 C4 04 add esp,4



2003年7月15日19:33:07 -0700, dp****@optushome.com .au (Dylan Nicholson)

写道:

我刚发布了一个可能的浮点错误(不确定
在哪里) ,并且从那以后发现:

浮动f = 5.15002;
双d = 5.15002;
if(float(d)< f)
puts( huh 1?);
float f2 = float(d);
if(f2< f)
put(huh 2?);

导致''huh 1''被打印,但不是''huh 2''。


首先,这似乎是c ++,而不是c,虽然概念是

在这种情况下基本相同。 VC6支持C90,而不支持C99,所以

上面有几个编译器错误。


其次,将编译器设置为符合模式:

/ Za禁用语言扩展(选中复选框)ANSI C

兼容性。与ANSI C不兼容的语言结构

标记为错误。请注意,这也会打开/ Op(改进Float

一致性)标志,这是此处所需的。


设置/ Za,不是 ;呵呵1也不是huh 2输出,并且没有

异常,并且行为符合。


但是,如果没有/ Za设置,VC将默认为浮动模式-point

值保留在寄存器中,并且在所有情况下都不进行类型转换

由标准规定。我得到了两个呵呵1和huh 2输出,根据VC的默认行为,这是我所期望的。


相对于你的第一篇文章,

float f = 5.15002;
double d = 5.15002;
if(d + FLT_EPSILON< f)
puts(" huh?");




当从double转换为
float时,f会被向上舍入,超过FLT_EPSILON。请注意,5.15002的类型为double。


非正式地,我在调试器中看到的是

5.1500201225281 = f(双倍)

5.1500201192093 = d + FLT_EPSILON

5.1500200000000 = d

所以我们得到的结果与我们在这里看到的一致。


正如另一张海报建议的那样,你可能想看看与浮点表示相关的问题




问候,

Bruce Wheeler




" Dylan Nicholson" < DP **** @ optushome.com.au>在消息中写道

news:73 ************************** @ posting.google.c om ...


(剪辑)

| float f = 5.15002;
| double d = 5.15002;
| if(float(d)< f)
| put(huh 1?);
| float f2 = float(d);
| if(f2< f)
| put(huh 2?);
|
|
|导致''huh 1''被打印,但不是''huh 2''。
|
|我不知道这是编译器程序(MSVC 6),FPU问题还是
什么!


< snip>

如果您首先将双精度数转换为浮点数,则两个数字都将被截断为6位数并且相等。
嗯,如果你看一下代码,那就是我所做的,在这两种情况下都是如此。
但是只有一个比较表现得出乎意料。
我看不到除了编译器错误或FPU指令集不一致之外,上面的内容怎么样(不幸的是我根本不熟悉FPU指令)。




这不是你在C中演员的方式。我不知道存在float()函数,

虽然。


应该是if((float)d< f)或者,确定优先级

if(((float)d)< f)


在任何情况下,由于浮点内部寄存器的处理方式,b / b
处理器的值通常比指定的
精度更高。无论好坏,C允许这样做。有时更精确是好的,

有时候很糟糕。


- glen

- glen


I just posted regarding a possible floating point error (not sure
where), and have since discovered that:

float f = 5.15002;
double d = 5.15002;
if (float(d) < f)
puts("huh 1?");
float f2 = float(d);
if (f2 < f)
puts("huh 2?");
Causes ''huh 1'' to be printed, but NOT ''huh 2''.

I can''t tell if this is a compiler program (MSVC 6), an FPU problem or
what!

The assembly code is:

6: float f = 5.15002;
00401028 C7 45 FC F7 CC A4 40 mov dword ptr [ebp-4],40A4CCF7h
7: double d = 5.15002;
0040102F C7 45 F4 D2 FB C6 D7 mov dword ptr
[ebp-0Ch],0D7C6FBD2h
00401036 C7 45 F8 9E 99 14 40 mov dword ptr [ebp-8],4014999Eh
8: if (float(d) < f)
0040103D DD 45 F4 fld qword ptr [ebp-0Ch]
00401040 D9 55 EC fst dword ptr [ebp-14h]
00401043 D8 5D FC fcomp dword ptr [ebp-4]
00401046 DF E0 fnstsw ax
00401048 F6 C4 01 test ah,1
0040104B 74 0D je main+4Ah (0040105a)
9: puts("huh 1?");
0040104D 68 24 60 42 00 push offset string "huh 1?"
(00426024)
00401052 E8 39 00 00 00 call puts (00401090)
00401057 83 C4 04 add esp,4
10: float f2 = float(d);
0040105A DD 45 F4 fld qword ptr [ebp-0Ch]
0040105D D9 5D F0 fstp dword ptr [ebp-10h]
11: if (f2 < f)
00401060 D9 45 F0 fld dword ptr [ebp-10h]
00401063 D8 5D FC fcomp dword ptr [ebp-4]
00401066 DF E0 fnstsw ax
00401068 F6 C4 01 test ah,1
0040106B 74 0D je main+6Ah (0040107a)
12: puts("huh 2?");
0040106D 68 1C 60 42 00 push offset string "huh 2?"
(0042601c)
00401072 E8 19 00 00 00 call puts (00401090)
00401077 83 C4 04 add esp,4

解决方案

In general, floating point numbers cannot be represented precisely.

You can probably find various texts on this by searching the web for IEEE
Floating Pointing with your favorite search engine.
One such reference that may be helpful is:

http://msdn.microsoft.com/library/de...us/vccore/html
/_core_why_floating_point_numbers_may_lose_precisio n.asp

If you build your program for debug, step thru it, and look at the memory
contents
(the actual hex values, not the converted base 10 representation) being
compared this will probably be clearer.

- joel
"Dylan Nicholson" <dp****@optushome.com.au> wrote in message
news:73**************************@posting.google.c om...

I just posted regarding a possible floating point error (not sure
where), and have since discovered that:

float f = 5.15002;
double d = 5.15002;
if (float(d) < f)
puts("huh 1?");
float f2 = float(d);
if (f2 < f)
puts("huh 2?");
Causes ''huh 1'' to be printed, but NOT ''huh 2''.

I can''t tell if this is a compiler program (MSVC 6), an FPU problem or
what!

The assembly code is:

6: float f = 5.15002;
00401028 C7 45 FC F7 CC A4 40 mov dword ptr [ebp-4],40A4CCF7h
7: double d = 5.15002;
0040102F C7 45 F4 D2 FB C6 D7 mov dword ptr
[ebp-0Ch],0D7C6FBD2h
00401036 C7 45 F8 9E 99 14 40 mov dword ptr [ebp-8],4014999Eh
8: if (float(d) < f)
0040103D DD 45 F4 fld qword ptr [ebp-0Ch]
00401040 D9 55 EC fst dword ptr [ebp-14h]
00401043 D8 5D FC fcomp dword ptr [ebp-4]
00401046 DF E0 fnstsw ax
00401048 F6 C4 01 test ah,1
0040104B 74 0D je main+4Ah (0040105a)
9: puts("huh 1?");
0040104D 68 24 60 42 00 push offset string "huh 1?"
(00426024)
00401052 E8 39 00 00 00 call puts (00401090)
00401057 83 C4 04 add esp,4
10: float f2 = float(d);
0040105A DD 45 F4 fld qword ptr [ebp-0Ch]
0040105D D9 5D F0 fstp dword ptr [ebp-10h]
11: if (f2 < f)
00401060 D9 45 F0 fld dword ptr [ebp-10h]
00401063 D8 5D FC fcomp dword ptr [ebp-4]
00401066 DF E0 fnstsw ax
00401068 F6 C4 01 test ah,1
0040106B 74 0D je main+6Ah (0040107a)
12: puts("huh 2?");
0040106D 68 1C 60 42 00 push offset string "huh 2?"
(0042601c)
00401072 E8 19 00 00 00 call puts (00401090)
00401077 83 C4 04 add esp,4



On 15 Jul 2003 19:33:07 -0700, dp****@optushome.com.au (Dylan Nicholson)
wrote:

I just posted regarding a possible floating point error (not sure
where), and have since discovered that:

float f = 5.15002;
double d = 5.15002;
if (float(d) < f)
puts("huh 1?");
float f2 = float(d);
if (f2 < f)
puts("huh 2?");
Causes ''huh 1'' to be printed, but NOT ''huh 2''.

First, this appears to be c++, not c, although the concepts are
essentially the same in this case. VC6 supports C90, and not C99, so
there are several compiler errors in the above.

Second, set your compiler to conforming mode:
/Za Disable Language Extensions (check box selected) ANSI C
compatibility. Language constructs not compatible with ANSI C are
flagged as errors. Note that this also turns on the /Op (Improve Float
Consistency) flag, which is what is required here.

With /Za set, neither "huh 1" nor "huh 2" is output, and there are no
anomalies, and the behavior is conforming.

However, without /Za set, VC will default to a mode where floating-point
values remain in registers, and are not type-converted in all cases
dictated by the standard. I got both "huh 1" and "huh 2" output, which
is what I would expect, given VC''s default behavior.

Relative to your first post,
float f = 5.15002;
double d = 5.15002;
if (d + FLT_EPSILON < f)
puts("huh?");



it would appear that f is rounded up when converted from double to
float, more than FLT_EPSILON. Note that 5.15002 has type double.

Informally, what I see in the debugger is
5.1500201225281 = f (as double)
5.1500201192093 = d + FLT_EPSILON
5.1500200000000 = d
so the result we get is consistent with what we see here.

As another poster has suggested, you may want to look into the problems
associated with floating-point representations.

Regards,
Bruce Wheeler



"Dylan Nicholson" <dp****@optushome.com.au> wrote in message
news:73**************************@posting.google.c om...

(snip)

| float f = 5.15002;
| double d = 5.15002;
| if (float(d) < f)
| puts("huh 1?");
| float f2 = float(d);
| if (f2 < f)
| puts("huh 2?");
|
|
| Causes ''huh 1'' to be printed, but NOT ''huh 2''.
|
| I can''t tell if this is a compiler program (MSVC 6), an FPU problem or
| what!


<snip>

If you first cast the double to a float, both numbers are
truncated to 6 digits and compare equal.


Um, if you look at the code, that''s exactly what I did, in both cases.
However only one of the comparisons behaves unexpectedly.
I can''t see how the above can be anything other than a compiler error
or a FPU instruction set inconsistency (unfortunately I''m not at all
familiar with FPU instructions).



That is not how you cast in C. I don''t know that a float() function exists,
though.

It should be if((float)d<f) or, to be sure about precedence
if(((float)d)<f)

In any case, because of the way the internal registers in the floating point
processor it is common for values to be held with a higher precision than
specified. Good or bad, C allows this. Sometimes more precision is good,
sometimes bad.

-- glen
-- glen


这篇关于浮点错误(更多信息)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆