Equal comparison of Floating Point Numbers

Source: Internet
Author: User
Equal comparison of Floating Point Numbers

Today, a buddy in the group -- Oh, to be exact, it should be a sister -- asked Python how to determine whether the decimal part of a floating point number is 0, the intention is to find a function with the same function as the fmod function in C language. This function is available in the math module in Python, but it raises the topic of floating point precision.

I suddenly thought that when I learned the C language, the teacher mentioned that the equal comparison of integers can be judged directly using =, but the comparison of floating point numbers cannot be simply compared using =. So how can we determine whether floating point numbers are equal?

Then google found the classic method: using the accuracy of the absolute value of the difference value to determine.

Specifically, F1 and F2 are two floating point numbers, and precision is the precision set by ourselves, such as 1e-6.

Then you can use FABS (F1-F2) <= precision
To determine whether F1 and F2 are equal.

If higher precision is required, set the precision to a smaller value.

 

 

A Daniel on the Internet said that this method still has problems:

"First, precision is an absolute data, that is, the absolute error in error analysis. Using a fixed value is not acceptable for the entire number field that the float type can express. For example, if the value of precision is 0.0001 and the value of two F1 and F2 is about 0.0001, it is obviously inappropriate. In addition, it is not suitable for data such as F1 and F2 with a size of 10000, because 10000 and 10001 can be equally authentic. It is only applicable when F1 or F2 is near 1 or 0 ."

 

The Daniel provides the following solutions:

"

Since the absolute error is not acceptable, we will naturally think of the relative error.

Bool isequal (float a, float B, float relerror ){


Return (FABS (a-B)/A) <relerror )? True: false;

}

This write is not complete, because it is compared with the first fixed parameter, then

Isequal (a, B, relerror)
Different results may be obtained from isequal (B, A, relerror ).

At the same time, if the first parameter is 0, it may be a division of 0 overflow.

This can be transformed

Select the division number as the absolute value of A and B.

Bool isequal (float a, float B, relerror)

{


If (FABS (a) <FABS (B) Return (FABS (a-B)/A)> relerror )? True: false;


Return (FABS (a-B)/B)> relerror )? True: false;

};

 

Is the relative error perfect?

No. In some special cases, the relative error cannot represent all

For example, when determining whether the three points in the space are collocated or not, you can use the method to determine the distance between the three points and the line segments formed by the other two points.

It is not enough to only use the relative error. When the distance between a line segment may be very long or long, the distance between the point and the line segment, and the length of the Line Segment, only when the relative error and absolute error are combined

A relatively complete comparison algorithm should be as follows:

Bool isequal (float a, float B, float abserror, float relerror)

{


If (A = B) Return true;


If (FABS (a-B) <abserror) return true;


If (FABS (A> B) Return (FABS (a-B)/A> relerror )? True: false;


Return (FABS (a-B)/B> relerror )? True: false;

}

This is complete.

"

 

Then the Daniel gave another "comparison algorithm ":

(Although the article is long, in order not to change the description of the original article, we will record it here according to the original article)

"

Let's first look at positive numbers.

According to the IEEE memory structure, the index is at a high level and the ending number is at a low level.

When the memory structure of floating point numbers is compared according to integers, the situation is also true.

Therefore, if we compare them here, the efficiency of using them as integers will be very high, for example

Float F1 = 1.23;

Float F2 = 1, 1.24

F1> F2
Founded

(Int &) F1> (Int &) F2
Also established

 

Furthermore, by carefully studying the floating point structure of IEEE, we can find that the floating point Precision problem mentioned in floating point comparison-not all floating point numbers can be accurately expressed.

The floating point numbers that can be precisely expressed are actually limited, that is, the IEEE enumerated for various situations are 2 ^ 32. What cannot be expressed occupies the majority

 

In the case of 32-bit IEEE, the ending number is 23 bits (meaning that the first digit is 1)

For floating-point numbers that can be accurately expressed, if we consider these 23 digits as integers, adding 1 means we can find the smallest floating-point number larger than the current floating-point number.

On the contrary, we calculate the difference between two floating point numbers and corresponding integers, the obtained integer indicates how many floating-point numbers can actually be expressed between two floating-point numbers (the corresponding indexes are the same, which is also effective when the indexes are different)

 

In this way, for two positive floating point numbers, their size can be compared with (Int &) F1-(Int &) F2
For comparison.

The result of the difference is actually a relative error.

This relative error is not equivalent to the relative error in the general sense.

It expresses the number of floating-point numbers that can be accurately expressed between two floating-point numbers.

In this way, it is more effective to control the comparison between two floating point numbers by specifying this threshold.

For two positive floating point numbers

Bool isequal (float F1, float F2, int absdelta)

{


If (ABS (Int &) F1-(Int &) F2) <absdelta) return true;

}

ABS instead of FABs is used here. The calculation gap in ASM is also very large.

 

The comparison of two negative numbers is the same.

Only the integer corresponding to the negative memory is added with 1, and the corresponding result is a smaller negative number.

 

However, there is no direct comparison between negative numbers and integers, because according to the IEEE Memory Structure

The positive and negative numbers are different, and the corresponding integers cannot be consecutive.

The smallest positive number is 0, and the corresponding integer is 0x00000000.

The smallest negative value is-0, and the corresponding integer is 0x80000000.

Don't be surprised-0

There are two 0's In the IEEE expression, one is + 0
One is-0

 

Interestingly, according to F1 = F2
+ 0 and-0 are equal.


By comparison, we can find that,

+ 0
The Positive floating point number can be directly compared by converting to an integer.

-0
And negative floating point numbers can be directly compared by converting to an integer

 

If we can connect them, the direct comparison of the entire integer method will be complete.

By comparing the structure of negative numbers, we can find a simple method:


Subtract-0 from the integer corresponding to the negative memory, and they are connected consecutively.

In addition, the better result is that after all the negative numbers are subtracted, the corresponding integers are also negative.

In this way, the entire integer comparison becomes continuous, and it is valid throughout the floating point range.

 

The final comparison algorithm is:

//
Function: bool isequal (float F1, float F2, int absdelta)

//
Function: Compares two floating point numbers to see if they are similar.

//
Input: F1, F2 two floating point numbers involved in the comparison

//
The number of floating-point numbers allowed between two floating-point numbers in absdelta that can be accurately expressed exists, which is equivalent to the relative error.

//
Output: True, two floating point numbers are equal; false
Two floating point numbers

//
Note: Only applicable to the IEEE 32-bit floating point structure

Bool isequal (float F1, float F2, int absdelta)

{


Int I1, I2;


I1 = (F1> 0 )? (Int &) F1): (Int &) F1-0x80000000 );


I2 = (F2> 0 )? (Int &) F2): (Int &) F2-0x80000000 );


Return (ABS (i1-i2) <absdelta )? True: false;

}

"

I have not understood the explanation of this Daniel. I have recorded it here for the time being and will continue reading it later. What others think is true and clear

 

Reference: http://blog.csdn.net/sharkw/article/details/1937581

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.