非整数类型的比较 [英] comparison on non-integer types

查看:54
本文介绍了非整数类型的比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨组,

我一直以为应用二元运算符,例如==,!=,< =或


> =两个double或float值是一个操作,结果是



定义良好。


现在,我'通过夹板传递一个程序[1]它说:


涉及双重类型的危险等式比较:

l_lnk1-> lnk_freq == l_lnk2- > lnk_freq

使用==或!= primitive直接比较两个真实(浮点数,双倍或长双精度值)

。这可能会产生意想不到的结果,因为

浮点表示是不精确的。相反,将

差异与FLT_EPSILON或DBL_EPSILON进行比较。


l_lnk1-> lnk_freq和l_lnk2-> lnk_freq被定义为双值。


写比较是否真的更好

(l_lnk1-> lnk_freq - l_lnk2-> lnk_freq< DBL_EPSILON)

或者在这种情况下夹板是否过于迂腐?


谢谢!


[1] http://www.splint.org/

-

Pietro Cerutti


PGP公钥:
http: //gahr.ch/pgp

解决方案

Pietro Cerutti写道:


Hi group,

我一直认为应用二元运算符,例如==,!=,< =或


> ; =两个double或float值是一个操作wh ich结果是



定义良好。


现在,我正在通过夹板传递程序[1]并且它说:


涉及双重类型的危险平等比较:

l_lnk1-> lnk_freq == l_lnk2-> lnk_freq

两real(float,double或long double)值直接比较

使用==或!= primitive。这可能会产生意想不到的结果,因为

浮点表示是不精确的。相反,将

差异与FLT_EPSILON或DBL_EPSILON进行比较。


l_lnk1-> lnk_freq和l_lnk2-> lnk_freq被定义为双精度值。


写比较是否真的更好

(l_lnk1-> lnk_freq - l_lnk2-> lnk_freq< DBL_EPSILON)

或者在这种情况下夹板是否过于迂腐?


谢谢!


[1] http://www.splint.org/



PS只是为了表明我已完成自己的作业:

n1124:6.2.5类型

18整数和浮动类型统称为算术类型。


n1123:6.5.9平等运营商

1平等表达式:

关系表达式

equality-expression == relational-expression

equality-expression!= relational-expression

约束

2以下其中一项应持有:

A?两个操作数都有算术类型;


因此,比较两个double值应该是完全合法的,例如==。

-

Pietro Cerutti


PGP公钥:
http://gahr.ch/pgp


Pietro Cerutti写道,On 05/09/07 18:59:
< blockquote class =post_quotes>
你好组,

我一直以为应用二元运算符如==,!=,< =或


=两个double或float值是一个操作,结果是



定义良好。


现在,我正在通过夹板[1]传递一个程序,它说:


涉及双重类型的危险等式比较:

l_lnk1-> ; lnk_freq == l_lnk2-> lnk_freq

使用==或!= primitive直接比较两个真实(浮点数,双倍或长双精度值)

。这可能会产生意想不到的结果,因为

浮点表示是不精确的。相反,将

差异与FLT_EPSILON或DBL_EPSILON进行比较。


l_lnk1-> lnk_freq和l_lnk2-> lnk_freq被定义为双值。


写比较是否真的更好

(l_lnk1-> lnk_freq - l_lnk2-> lnk_freq< DBL_EPSILON)

或者在这种情况下夹板是否过于迂腐?



最好了解真正的问题,然后根据您的具体情况做出适当的b $ b b决定。


基本问题是计算机是有限的。因此,当使用浮动或双倍工作
时,您往往只得到近似结果。确切地说

你正在做什么以及你的特定实施的变幻无常将决定这些

错误增长的速度和方向。那么问题是你的

等式测试对于理论上应该是理论上相等的数字理论上应该是不同的还是假的数字是否更好。


我建议你看一下comp.lang.c常见问题的部分
http://c-faq.com/ 这些都与浮点数有关。没有

意味着详尽无遗,但这是一个开始。

-

Flash Gordon

< br>

在文章< 97 *************************** @ news.hispeed.ch> ;,

Pietro Cerutti< ga ** @ gahr.chwrote:


>现在,我正在通过夹板传递程序[1]并且它说:


>涉及双重类型的危险等式比较:
l_lnk1-> lnk_freq == l_lnk2-> lnk_freq
使用==或!= primitive直接比较两个真实(float,double或long double)值。这可能会产生意外的结果,因为
浮点表示是不精确的。相反,将
差异与FLT_EPSILON或DBL_EPSILON进行比较。


>写比较是否真的更好
(l_lnk1-> lnk_freq - l_lnk2-> lnk_freq< DBL_EPSILON在这种情况下,夹板是否过于迂腐?



拆分是正确的。如果你有两个浮点数,X和Y,

和一个不是通过分配另一个来创建的

(例如,Y = X;),那么即使你使用相同的数字代码来计算它们,数字也不一定比较




例如,


X = 1./7。; Y = 1./7 .;


X和Y不一定比较相等:即使用这个简单的例子,X和Y最终可能会有所不同最后一点。


如果您有更复杂的配方,例如


X = 9./10。 Y = 1./100。 * 90 .;


然后不仅仅是最后一点可能会有所不同。


另一个例子:Y = P + X - P ;然后X和Y不一定会相同,即使P是0,也不一定是


如果你 - 使用了直接作业,


Y = X;


然后如果我的记忆是正确的,那么Y应该根据抽象机器比较等于X

,但是(如果我的内存是正确的),

有x86机器的编译器,其中抽象机器
$最后一位可以违反b $ b语义:X可能在一个

80位浮点寄存器中,如果编译器没有采用

的时间来舍入在每一步计算为64位

[为了速度,或者因为用户想要更高的准确度],那么如果Y在内存中而不是在CPU寄存器中,则需要
),存储

到Y轮(或截断)值; X == Y

的比较可能会将Y加载到x86上的80位CPU寄存器中,如果

则舍入为Y的80位扩展名为'碰巧比较

完全等于80位* un *舍入X,比较将失败。

我相信这种行为违反了C''好像规则,但确实在实践中发生了


-

没有人有权摧毁他人的信仰通过

要求经验证据。 - Ann Landers


Hi group,
I always thought that applying a binary operator such as ==, !=, <= or

>= to two double or float values was an operation which results were

well defined.

Now, I''m passing a program through splint[1] and it says:

Dangerous equality comparison involving double types:
l_lnk1->lnk_freq == l_lnk2->lnk_freq
Two real (float, double, or long double) values are compared directly
using == or != primitive. This may produce unexpected results since
floating point representations are inexact. Instead, compare the
difference to FLT_EPSILON or DBL_EPSILON.

l_lnk1->lnk_freq and l_lnk2->lnk_freq being defined as double values.

Is it really better to write the comparison as
(l_lnk1->lnk_freq - l_lnk2->lnk_freq < DBL_EPSILON)
or is splint being over-pedantic in this situation?

Thank you!

[1] http://www.splint.org/
--
Pietro Cerutti

PGP Public Key:
http://gahr.ch/pgp

解决方案

Pietro Cerutti wrote:

Hi group,
I always thought that applying a binary operator such as ==, !=, <= or

>= to two double or float values was an operation which results were

well defined.

Now, I''m passing a program through splint[1] and it says:

Dangerous equality comparison involving double types:
l_lnk1->lnk_freq == l_lnk2->lnk_freq
Two real (float, double, or long double) values are compared directly
using == or != primitive. This may produce unexpected results since
floating point representations are inexact. Instead, compare the
difference to FLT_EPSILON or DBL_EPSILON.

l_lnk1->lnk_freq and l_lnk2->lnk_freq being defined as double values.

Is it really better to write the comparison as
(l_lnk1->lnk_freq - l_lnk2->lnk_freq < DBL_EPSILON)
or is splint being over-pedantic in this situation?

Thank you!

[1] http://www.splint.org/

P.S. just to show that I''ve done my own homework:
n1124: 6.2.5 Types
18 Integer and floating types are collectively called arithmetic types.

n1123: 6.5.9 Equality operators
1 equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
Constraints
2 One of the following shall hold:
a?? both operands have arithmetic type;

Thus, it should be fully legal to compare two double values with, e.g., ==.
--
Pietro Cerutti

PGP Public Key:
http://gahr.ch/pgp


Pietro Cerutti wrote, On 05/09/07 18:59:

Hi group,
I always thought that applying a binary operator such as ==, !=, <= or

= to two double or float values was an operation which results were

well defined.

Now, I''m passing a program through splint[1] and it says:

Dangerous equality comparison involving double types:
l_lnk1->lnk_freq == l_lnk2->lnk_freq
Two real (float, double, or long double) values are compared directly
using == or != primitive. This may produce unexpected results since
floating point representations are inexact. Instead, compare the
difference to FLT_EPSILON or DBL_EPSILON.

l_lnk1->lnk_freq and l_lnk2->lnk_freq being defined as double values.

Is it really better to write the comparison as
(l_lnk1->lnk_freq - l_lnk2->lnk_freq < DBL_EPSILON)
or is splint being over-pedantic in this situation?

It is best to understand the real issues and then make an appropriate
decision based on your particular situation.

The basic problem is that computers are finite. Therefore when working
with float or double you tend to get only approximate results. Exactly
what you are doing with them and the vagaries of your particular
implementation will determine how fast and in what direction those
errors grow. Then there is the question of whether it is better for your
equality test to return true for numbers that theoretically should be
different or false for numbers that theoretically be equal.

I suggest you look at the section of the comp.lang.c FAQ at
http://c-faq.com/ that is all about floating point numbers. It is by no
means exhaustive, but it is a start.
--
Flash Gordon


In article <97***************************@news.hispeed.ch>,
Pietro Cerutti <ga**@gahr.chwrote:

>Now, I''m passing a program through splint[1] and it says:

>Dangerous equality comparison involving double types:
l_lnk1->lnk_freq == l_lnk2->lnk_freq
Two real (float, double, or long double) values are compared directly
using == or != primitive. This may produce unexpected results since
floating point representations are inexact. Instead, compare the
difference to FLT_EPSILON or DBL_EPSILON.

>Is it really better to write the comparison as
(l_lnk1->lnk_freq - l_lnk2->lnk_freq < DBL_EPSILON)
or is splint being over-pedantic in this situation?


Split is correct. If you have two floating point numbers, X and Y,
and one was not created by assigning the other to it
(e.g., Y = X; ), then the numbers will not necessarily compare
the same even if you use the same numeric code to compute them.

For example,

X = 1./7.; Y = 1./7.;

X and Y will not necessarily compare equal: even with this
simple example, X and Y could end up differing in the last bit.

And if you have more complex formulations such as

X = 9./10.; Y = 1./100. * 90.;

then more than just the last bit could end up differing.

Another example: Y = P + X - P; then X and Y will not necessarily
come out the same, not even if P is 0.
If you -have- used a direct assignment,

Y = X;

then if my memory is correct, then Y "should" compare equal to X
according to the abstract machine, but (if my memory is correct),
there are compilers for x86 machines where the abstract machine
semantics can be violated for the last bit: X might be in an
80 bit floating point register, and if the compiler does not take
the time to round the calculation to 64 bits at each step
[for speed, or because the user wants higher accuracy], then
if Y is in memory (instead of in a CPU register), the storage
to Y rounds (or truncates) the value; the comparison of X == Y
would likely load Y into an 80-bit CPU register on x86, and if
the 80-bit extension of the rounded Y doesn''t happen to compare
exactly equal to the 80-bit *un*rounded X, the comparison will fail.
I believe this behaviour violates C''s "as if" rules, but it does
happen in practice.
--
"No one has the right to destroy another person''s belief by
demanding empirical evidence." -- Ann Landers


这篇关于非整数类型的比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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