为什么 24.0000 在 MATLAB 中不等于 24.0000? [英] Why is 24.0000 not equal to 24.0000 in MATLAB?

查看:19
本文介绍了为什么 24.0000 在 MATLAB 中不等于 24.0000?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个程序,我需要删除存储在矩阵中的重复点.问题在于,当检查这些点是否在矩阵中时,MATLAB 无法在矩阵中识别它们,尽管它们存在.

在下面的代码中,intersections函数得到了交点:

[points(:,1), points(:,2)] = 交叉点(...obj.modifiedVGVertices(1,:), obj.modifiedVGVertices(2,:), ...[顶点1(1)顶点2(1)],[顶点1(2)顶点2(2)]);

结果:

<代码>>>积分点数 =12.0000 15.000033.0000 24.000033.0000 24.0000>>顶点 1顶点 1 =1215>>顶点2顶点 2 =3324

应该从结果中消除两个点(vertex1vertex2).它应该通过以下命令完成:

points = points((points(:,1) ~= vertex1(1)) | (points(:,2) ~= vertex1(2)), :);点=点((点(:,1)〜=顶点2(1))|(点(:,2)〜=顶点2(2)),:);

这样做之后,我们得到了意想不到的结果:

<代码>>>积分点数 =33.0000 24.0000

结果应该是一个空矩阵.如您所见,第一对(或第二对?)[33.0000 24.0000] 已被淘汰,但第二对没有被淘汰.

然后我检查了这两个表达式:

<代码>>>点(1)~=顶点2(1)答案 =0>>点(2)~=顶点2(2)答案 =1 % <-- 表示 24.0000 不等于 24.0000?

有什么问题?

<小时>

更令人惊讶的是,我制作了一个只有这些命令的新脚本:

points = [12.0000 15.000033.0000 24.000033.0000 24.0000];顶点 1 = [12 ;15];顶点 2 = [33 ;24];点=点((点(:,1)〜=顶点1(1))|(点(:,2)〜=顶点1(2)),:);点=点((点(:,1)〜=顶点2(1))|(点(:,2)〜=顶点2(2)),:);

预期结果:

<代码>>>积分点数 =空矩阵:0×2

解决方案

您遇到的问题与

然后可以使用以下公式找到实际值:

这种格式允许在 10^-308 到 10^308 范围内的数字表示.对于 MATLAB,您可以从 realminrealmax:

<代码>>>Realmin答案 =2.225073858507201e-308>>最大答案 =1.797693134862316e+308

由于用于表示浮点数的位数是有限的,因此在上述给定范围内可以表示的有限数是有限的.计算通常会产生与这些有限表示之一不完全匹配的值,因此必须对这些值进行四舍五入.这些机器精度误差以不同的方式表现出来,如上述示例所述.>

为了更好地理解这些舍入误差,查看函数提供的相对浮点精度很有用 eps,量化从给定数字到下一个最大浮点表示的距离:

<代码>>>每股收益(1)答案 =2.220446049250313e-16>>每股收益(1000)答案 =1.136868377216160e-13

请注意,精度相对与所表示的给定数字的大小有关;较大的数字将在浮点表示之间具有较大的距离,因此小数点后的精度位数较少.对于某些计算,这可能是一个重要的考虑因素.考虑以下示例:

<代码>>>format long % 显示全精度>>x = rand(1, 10);% 获取 0 到 1 之间的 10 个随机值>>a = mean(x) % 取平均值一 =0.587307428244141>>b = mean(x+10000)-10000 % 在不同的尺度上取平均值,然后移回乙 =0.587307428244458

注意,当我们将 x 的值从范围 [0 1] 移动到范围 [10000 10001] 时,计算一个均值,然后减去用于比较的平均偏移量,我们得到一个与最后 3 个有效数字不同的值.这说明了数据的偏移或缩放如何改变对其执行的计算的准确性,这是某些问题必须考虑的事情.

I am writing a program where I need to delete duplicate points stored in a matrix. The problem is that when it comes to check whether those points are in the matrix, MATLAB can't recognize them in the matrix although they exist.

In the following code, intersections function gets the intersection points:

[points(:,1), points(:,2)] = intersections(...
    obj.modifiedVGVertices(1,:), obj.modifiedVGVertices(2,:), ...
    [vertex1(1) vertex2(1)], [vertex1(2) vertex2(2)]);

The result:

>> points
points =
   12.0000   15.0000
   33.0000   24.0000
   33.0000   24.0000

>> vertex1
vertex1 =
    12
    15

>> vertex2    
vertex2 =
    33
    24

Two points (vertex1 and vertex2) should be eliminated from the result. It should be done by the below commands:

points = points((points(:,1) ~= vertex1(1)) | (points(:,2) ~= vertex1(2)), :);
points = points((points(:,1) ~= vertex2(1)) | (points(:,2) ~= vertex2(2)), :);

After doing that, we have this unexpected outcome:

>> points
points =
   33.0000   24.0000

The outcome should be an empty matrix. As you can see, the first (or second?) pair of [33.0000 24.0000] has been eliminated, but not the second one.

Then I checked these two expressions:

>> points(1) ~= vertex2(1)
ans =
     0
>> points(2) ~= vertex2(2)
ans =
     1   % <-- It means 24.0000 is not equal to 24.0000?

What is the problem?


More surprisingly, I made a new script that has only these commands:

points = [12.0000   15.0000
          33.0000   24.0000
          33.0000   24.0000];

vertex1 = [12 ;  15];
vertex2 = [33 ;  24];

points = points((points(:,1) ~= vertex1(1)) | (points(:,2) ~= vertex1(2)), :);
points = points((points(:,1) ~= vertex2(1)) | (points(:,2) ~= vertex2(2)), :);

The result as expected:

>> points
points =  
   Empty matrix: 0-by-2

解决方案

The problem you're having relates to how floating-point numbers are represented on a computer. A more detailed discussion of floating-point representations appears towards the end of my answer (The "Floating-point representation" section). The TL;DR version: because computers have finite amounts of memory, numbers can only be represented with finite precision. Thus, the accuracy of floating-point numbers is limited to a certain number of decimal places (about 16 significant digits for double-precision values, the default used in MATLAB).

Actual vs. displayed precision

Now to address the specific example in the question... while 24.0000 and 24.0000 are displayed in the same manner, it turns out that they actually differ by very small decimal amounts in this case. You don't see it because MATLAB only displays 4 significant digits by default, keeping the overall display neat and tidy. If you want to see the full precision, you should either issue the format long command or view a hexadecimal representation of the number:

>> pi
ans =
    3.1416
>> format long
>> pi
ans =
   3.141592653589793
>> num2hex(pi)
ans =
400921fb54442d18

Initialized values vs. computed values

Since there are only a finite number of values that can be represented for a floating-point number, it's possible for a computation to result in a value that falls between two of these representations. In such a case, the result has to be rounded off to one of them. This introduces a small machine-precision error. This also means that initializing a value directly or by some computation can give slightly different results. For example, the value 0.1 doesn't have an exact floating-point representation (i.e. it gets slightly rounded off), and so you end up with counter-intuitive results like this due to the way round-off errors accumulate:

>> a=sum([0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]);  % Sum 10 0.1s
>> b=1;                                               % Initialize to 1
>> a == b
ans =
  logical
   0                % They are unequal!
>> num2hex(a)       % Let's check their hex representation to confirm
ans =
3fefffffffffffff
>> num2hex(b)
ans =
3ff0000000000000

How to correctly handle floating-point comparisons

Since floating-point values can differ by very small amounts, any comparisons should be done by checking that the values are within some range (i.e. tolerance) of one another, as opposed to exactly equal to each other. For example:

a = 24;
b = 24.000001;
tolerance = 0.001;
if abs(a-b) < tolerance, disp('Equal!'); end

will display "Equal!".

You could then change your code to something like:

points = points((abs(points(:,1)-vertex1(1)) > tolerance) | ...
                (abs(points(:,2)-vertex1(2)) > tolerance),:)


Floating-point representation

A good overview of floating-point numbers (and specifically the IEEE 754 standard for floating-point arithmetic) is What Every Computer Scientist Should Know About Floating-Point Arithmetic by David Goldberg.

A binary floating-point number is actually represented by three integers: a sign bit s, a significand (or coefficient/fraction) b, and an exponent e. For double-precision floating-point format, each number is represented by 64 bits laid out in memory as follows:

The real value can then be found with the following formula:

This format allows for number representations in the range 10^-308 to 10^308. For MATLAB you can get these limits from realmin and realmax:

>> realmin
ans =
    2.225073858507201e-308
>> realmax
ans =
    1.797693134862316e+308

Since there are a finite number of bits used to represent a floating-point number, there are only so many finite numbers that can be represented within the above given range. Computations will often result in a value that doesn't exactly match one of these finite representations, so the values must be rounded off. These machine-precision errors make themselves evident in different ways, as discussed in the above examples.

In order to better understand these round-off errors it's useful to look at the relative floating-point accuracy provided by the function eps, which quantifies the distance from a given number to the next largest floating-point representation:

>> eps(1)
ans =
     2.220446049250313e-16
>> eps(1000)
ans =
     1.136868377216160e-13

Notice that the precision is relative to the size of a given number being represented; larger numbers will have larger distances between floating-point representations, and will thus have fewer digits of precision following the decimal point. This can be an important consideration with some calculations. Consider the following example:

>> format long              % Display full precision
>> x = rand(1, 10);         % Get 10 random values between 0 and 1
>> a = mean(x)              % Take the mean
a =
   0.587307428244141
>> b = mean(x+10000)-10000  % Take the mean at a different scale, then shift back
b =
   0.587307428244458

Note that when we shift the values of x from the range [0 1] to the range [10000 10001], compute a mean, then subtract the mean offset for comparison, we get a value that differs for the last 3 significant digits. This illustrates how an offset or scaling of data can change the accuracy of calculations performed on it, which is something that has to be accounted for with certain problems.

这篇关于为什么 24.0000 在 MATLAB 中不等于 24.0000?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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