Switch for floating !!

G

Guest

in an earlier post you implied unordered was equivalent
to equal. So if they aren't ordered they can be considered
to be equivalent.

Which looks ok for fabs. Lets say 'e' is just smaller
than epsilon

2.0 == 2.0
2.0 == 2.0 + e
2.0 != 1.0
2.0 != 2.9
no. fabs() was present in C89 (the 1989 C standard)
and maybe even earlier.


that looks dubious

so now try your abs version

2.0 == 2.9

which looks wrong to me...
 
R

Richard Tobin

A floating point value can be an integer value, such as 3.0.
However, whether or not that is the case, how does that constitute
an answer to the question? The question was not about what the
standard requires. The question was, does the standard require it?
[/QUOTE]
No, that is a non-integral value which has a zero fractional part.
Really.

There may be interesting discussions to be had about whether a
mathematical integer is the same as the corresponding real number,
but none of them apply to C's ints and doubles.

-- Richard
 
B

Barry Schwarz

sorry, fabs is C99, too.
i meant:
#define isunordered(x,y) (abs(x-y)>FLT_EPSILON)
add more parens to use it for expressions

In addition to all the other problems that have been pointed out, when
you finally do calculate the absolute difference between the values,
you need to compare it against a "scaled adjusted" value of
FLT_EPSILON. FLT_EPSILON is the smallest value that can be added to
1.0F to produce a different value. A typical value is 1E-5. If the
two values in question were 1E-20 and 1E-21, comparing against 1E-5
makes no sense.
 
M

mijoryx

no. fabs() was present in C89 (the 1989 C standard)
and maybe even earlier.


that looks dubious

appologies.
clearly i should not attempt to post things right before
going to bed (better to read it again with brighter eyes).
i confess i know next to nothing about isunordered
(yes, yes, don't make claims unless you're sure. point taken). my
actual code uses
fabsf(a.f - b.f) > FLT_EPSILON
but splint complained about unknown function fabsf
so while trying to make it happy, the code briefly
became
fabs(a.f - b.f) > FLT_EPSILON
which became garbled in my memory as fabs and abs.
so erroneous boasting and sleepy fingers aside,
what's the best test for "close-enough" floats?
the program above in the thread makes no attempt to
do this, relying on an external mental model of
the arithmetic to proclaim "approximately".

luser-ex-trolley
 
K

Keith Thompson

so erroneous boasting and sleepy fingers aside,
what's the best test for "close-enough" floats?
[...]

I don't think there is a "best test" for "close-enough" floats.

For integers, of course, equality is easy; two integers are either
equal or unequal, and even two very close numbers like 2147483646 and
2147483647 are clearly unequal. But even for integers, you might want
to know whether two values are "close enough" for some purpose.
Obviously the meaning of "close enough" depends on just what your
purpose is.

Since stored floating-point values, unlike integer values, are usually
approximations of some mathematical real value, comparing two stored
values for equality is often not useful, so we have to fall back to
some kind of "close enough" comparison. But determining what's "close
enough" depends on the application, and in particular on how the two
values being compared were computed.
 
M

mijoryx

Obviously the meaning of "close enough" depends on just what your
purpose is.

Since stored floating-point values, unlike integer values, are usually
approximations of some mathematical real value, comparing two stored
values for equality is often not useful, so we have to fall back to
some kind of "close enough" comparison.  But determining what's "close
enough" depends on the application, and in particular on how the two
values being compared were computed.

understood. how about some specifics.
I'd like to be able to compare floats in a
coordinate pair to determine if they will result
in the same XPoint (pair of short integers)
after passing through the same transformation
matrix and converted to shorts.
fabsf(a.f-b.f)>FLT_EPSILON
appears to be working (I don't expect to be using
values that push the boundaries of the float
representation). I need floats (or maybe fixed-point)
to use fractional scaling and sin and cos for rotations.
am i going to run into trouble comparing cos(0.0)
with 1.0?
--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

that's such a great show.
luXer-ex-troXX
 
B

Bartc

understood. how about some specifics.
I'd like to be able to compare floats in a
coordinate pair to determine if they will result
in the same XPoint (pair of short integers)
after passing through the same transformation
matrix and converted to shorts.
fabsf(a.f-b.f)>FLT_EPSILON
appears to be working (I don't expect to be using
values that push the boundaries of the float
representation). I need floats (or maybe fixed-point)
to use fractional scaling and sin and cos for rotations.
am i going to run into trouble comparing cos(0.0)
with 1.0?

cos(0) is likely to be exactly 1.0, but in general there will be problems.

Suppose you have a 2x2 rotation matrix and want to find out if it specifies
a rotation of exactly 90 degrees, it's unlikely to be an exact match with
((0 1) (-1 0)), depending on how it was calculated. (For example, try
combining two matrices each rotating 45 degrees.)

(In this example, you might apply rounding to the matrix, so that
((0.000009929, 0.99999352),(-1.000000271,-0.00000994)) 'snaps' to ((0.0,
1.0),(-1.0,0.0)), which will match with ((0,1),(-1,0)). You can then assume
a 90 degree rotation, but use the adjusted matrix to do the calculations.)
 
M

mijoryx

cos(0) is likely to be exactly 1.0, but in general there will be problems..

Suppose you have a 2x2 rotation matrix and want to find out if it specifies
a rotation of exactly 90 degrees, it's unlikely to be an exact match with
((0 1) (-1 0)), depending on how it was calculated. (For example, try
combining two matrices each rotating 45 degrees.)

(In this example, you might apply rounding to the matrix, so that
((0.000009929, 0.99999352),(-1.000000271,-0.00000994)) 'snaps' to ((0.0,
1.0),(-1.0,0.0)), which will match with ((0,1),(-1,0)). You can then assume
a 90 degree rotation, but use the adjusted matrix to do the calculations.)

It's looking like 1e-5 will suit my purposes better than
FLT_EPSILON. But I just discovered that this is all
wholy unnecessary since XFillPolygon will add a
closing segment by itself (I had been comparing the
ending and beginning points (in userspace, hence floats)
to decide whether to add a copy of the beginning
point to the path before handing it off to XFillPolygon.
I do still need to compare floats in other contexts,
but these are likely to be identical copies so direct
comparison will work (or maybe fabsf>1e-5).

Thanks to all for the advice and tollerance.

luXer-ex-troXX
 
C

CBFalconer

James said:
CBFalconer wrote:
.... snip ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you don't know the answer to the question, that's fine; but
please don't state that "the standard demands integers" as if it
were an answer to the question "why does the standard demand
integers?". If the standard did not demand integers, there would
still be nothing to prevent the implementation from using jump
tables when integers were in fact used.

If you bother to read the portion you quoted, above, you may notice
an example indicating why integers are needed.
 
C

CBFalconer

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No, that is an integral value expressed in a floating point type. The
literals 3, 3U, 3LL, 3.0, 3.0F, '\03', L'\03' all have different types,
but they all represent the same value, which is an integral value.


If you don't know the answer to the question, that's fine; but please
don't state that "the standard demands integers" as if it were an answer
to the question "why does the standard demand integers?".

Don't make such intimations. If you examine the quote above, you
will see what the question actually was.

And a possible implementation of 32 bit floating point could
express 3.0 as (hex):

7e 80 00 00

in place of:

00 00 00 03 (hi byte first, integer)

and these patterns will have a hard time indexing the same location
in a jump table. If you have no idea how floating point values are
built, say so.
 
K

karthikbalaguru

Interesting !!
Do you mean to say that C does not have facility for exact Floating
Point
number validation or processing irrespective of the type of
processor ?

See FAQ (http://c-faq.com/), esp. 14.1, 14.4a and 14.5.

You might also google for "What Every Computer Scientist Should Know About
Floating-Point Numbers [or was it really Arithmetics?]" by D. Goldberg.

Interesting info !! :):)

Karthik Balaguru
 
K

karthikbalaguru

C has the facility. The processor cannot produce the desired values.
for example
#include <stdio.h>
int main(void){
double x;
for (x = 0; x < 1.0; x += .1)
;
if (x == 1.0)
puts("Exact");
else
puts("Approximate");
return 0;
}
prints "Approximate" on most systems in use today. The reason is that
while 1.0 can be represented exactly on all systems, 0.1 cannot be on
most. I believe this is called limited precision.

(If I activate the decimal floating point feature of my system, it
prints "Exact" but that is why I said most, not all. Changing the
third clause of the for statement to
x += 1./11.
will result in "Approximate" on all systems I know of.)




It does. You are under the mistaken impression that "arithmetic"
performed on a CPU follows the rules of arithmetic you learned in
school. On most systems
x = 999999999999999999999999.0;
x -= 1.0;
does not result in a change to the value of x. I believe this is
called limited significance.




Yes, many do. One method: Instead of comparing for exact equality,
they compare for very small differences. Something along the lines of
replacing my if statement above with
if (fabs(x-1.0) < 1e-8)

Cool idea !!
Search the archives. This has been discussed many times in great
detail.

hmm. I will try to look into those archives also.

Karthik
 
G

Guest

please don't top-post. Post your reply after the text you
are replying to. I have re-arranged your post.


this can never be true

this can never be true
Little modification:
You shoud do something like this:

#include <stdio.h>
#include <math.h>

// because 1.0 != 1.0 in floating point system

since when?
bool float_equal(float& a, float& b, float eps)

this is not C. It's pretty crap c++ as well
{
    return (fabs(b-a)<eps);

}

int main(void)
{
    float a = 10;

    if (a == 1)
        printf("1 \n");
    else if  (a == 2.5)
        printf("2.5 \n");
    else
        printf("Other Number \n");
    return 0;}

you never call float_equal()
 
J

James Kuyper

CBFalconer said:
If you bother to read the portion you quoted, above, you may notice
an example indicating why integers are needed.

Since I referred to the portion you underlined in my response, in the
course of refuting the idea that allowing jump tables makes integers a
necessity, I think you should have been able to concluded that I did in
fact read that portion.


The fact that you did not reach that conclusion suggests to me that you
didn't bother reading the last paragraph of my response. Let me expand
on the counterargument that you apparently didn't notice. Let's assume
the following:

1) The standard is modified as follows (Note: I am NOT proposing that it
be changed in this fashion, I'm explaining why the reasons you've given
are insufficient argument against changing it in this fashion).
a) 6.8.4.2p1: allow the controlling expression in a switch() statement
to have any scalar type.
b) 6.8.4.2p3: allow the expression in a case label to be any constant
expression with scalar type.

2) A program contains a switch statement for which a jump table would be
a good way to implement it, under the current rules.

What feature of the changes to the standard described in item 1) would
prevent an implementation from using a jump table to implement the
switch statement described in item 2?
 
J

James Kuyper

CBFalconer said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

My apologies for the confusion: that last sentence was supposed to have
the word "why" just before the word "does".
....

And a possible implementation of 32 bit floating point could
express 3.0 as (hex):

7e 80 00 00

in place of:

00 00 00 03 (hi byte first, integer)

and these patterns will have a hard time indexing the same location
in a jump table.

The expressions used in case labels are required to be converted to the
promoted type of the controlling expression before comparison (the
conversion would normally occur at compile time). Therefore, the fact
that those case label expressions might have a different representation
than the controlling expression before conversion is irrelevant.

I'll readily concede that having a controlling expression that is a
floating point type would make it less likely for jump tables to be
feasible, though it would still be possible in certain special cases. So
what? The same is true if the controlling expression has the type
intmax_t and the case label expressions have no simple pattern. The
standard does not require implementation by jump tables, it only allows
implementation by jump tables.

If the standard were changed to allow non-integral controlling
expressions in switch() statements, that change would not in any way
prevent the use of jump tables for any switch() statement that is
allowed under the current rules, if a jump table happens to be a good
way to implement that statement.

The key issue with allowing floating point controlling expressions is
not whether it would be feasible to support them, but whether it would
be a good idea to encourage people to use them. Writing a switch()
statement with a floating point controlling expression would be a bad
idea, even if it were allowed, for precisely the same reason it would be
a bad idea to write the corresponding series of if-else statements.
That's because the conditions of the corresponding if()'s would compare
floating point values for equality, a reasonable thing to do only in
certain special cases.
 
C

CBFalconer

James said:
.... snip ...

My apologies for the confusion: that last sentence was supposed
to have the word "why" just before the word "does".
.... snip ...

The key issue with allowing floating point controlling expressions
is not whether it would be feasible to support them, but whether
it would be a good idea to encourage people to use them. Writing a
switch() statement with a floating point controlling expression
would be a bad idea, even if it were allowed, for precisely the
same reason it would be a bad idea to write the corresponding
series of if-else statements. That's because the conditions of the
corresponding if()'s would compare floating point values for
equality, a reasonable thing to do only in certain special cases.

Among other things the present restrictions make it easy for the
compiler to examine the set of switch values (they are all listed
in the statement) and decide between generating if/else expressions
or a jump table. That decision can result in major savings in code
space and/or execution time.

I'm glad you have identified the fundamental cause of our
'argument', which really doesn't exist. It shows how much
difference one small missing word can cause.
 
K

Keith Thompson

CBFalconer said:
Among other things the present restrictions make it easy for the
compiler to examine the set of switch values (they are all listed
in the statement) and decide between generating if/else expressions
or a jump table. That decision can result in major savings in code
space and/or execution time.
[...]

Allowing floating-point controlling expressions would not make the
compiler's job any more difficult. It could still generate a jump
table in all the cases where it can do so now, and detecting those
cases is at worst trivially more difficult (if it's floating-point,
don't use a jump table).

There are good reasons for disallowing floating-point controlling
expressions, but difficulty for the compiler isn't one of them.
 
A

Antoninus Twink

James said:
The key issue with allowing floating point controlling expressions
is not whether it would be feasible to support them, but whether
it would be a good idea to encourage people to use them.
[snip]

Among other things the present restrictions make it easy for the
compiler to examine the set of switch values (they are all listed
in the statement) and decide between generating if/else expressions
or a jump table.

My god, you really have completely lost the power of logical thought,
haven't you? (I'm charitably assuming that you once possessed it, before
old age turned your brain into mush.)

I truly wonder that James Kupyer or anyone else can possibly have the
patience to try to conduct a technical discussion with you. The rest of
us are jumping up and down with frustration just watching your repeated
failures to grasp the simplest point that's made to you.
 
C

CBFalconer

James said:
Since I referred to the portion you underlined in my response, in the
course of refuting the idea that allowing jump tables makes integers a
necessity, I think you should have been able to concluded that I did in
fact read that portion.

The fact that you did not reach that conclusion suggests to me that you
didn't bother reading the last paragraph of my response. Let me expand
on the counterargument that you apparently didn't notice. Let's assume
the following:

The following is a copy of my original reply to you. It includes
every word of your reply (as evidenced by the absence of <snip>
markers). In that light, I cannot follow your 'did not read'
comment. I answered the question you posed. I included an example
showing why the standard was so written.

! James Kuyper wrote:
!> CBFalconer wrote:
!>> karthikbalaguru wrote:
!>>
!>>> Why does the switch case statement does not have support
!>>> for floating points ?
!>>
!>> Because a floating point value is not an integer value.
!>
!> A floating point value can be an integer value, such as 3.0.
!>
!> However, whether or not that is the case, how does that
constitute
!> an answer to the question? The question was not about what the
!> standard requires. The question was, does the standard require
it?
!
! No, that is a non-integral value which has a zero fractional
part.
! Really. And yes, the standard demands integers. They may be
used
! to index a jump table, for example.

.... snip ...
What feature of the changes to the standard described in item 1)
would prevent an implementation from using a jump table to
implement the switch statement described in item 2?

In a separate answer somewhere in this thread I gave an example of
floating and integer representation of the number 3. Remember that
the idea is to have rapid execution. Any such intermixing of
representation would require fairly extensive code to test and
convert the representation, before indexing a pointer to a jump
table with it. Or it would require two separate sets of code
generated. Any such is contrary to the spirit of C, and totally
unnecessary. At worst, avoidance requires anointing the switch
statement with a cast.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,738
Latest member
JinaMacvit

Latest Threads

Top