Matlab дакладнасць: простае адніманне ня роўны нулю

Я вылічыць гэтую простую суму на Matlab:

2*0.04-0.5*0.4^2 = -1.387778780781446e-017

але вынік не роўны нулю. Што я магу зрабіць?

1
Аналагічнае пытанне: Чаму 24,0000 ня роўны 24.0000 у MATLAB?
дададзена аўтар Amro, крыніца
таксама значна больш відавочны прыклад: 0,3 - 0,1 * 3 , які дае 5.5511e-017 .
дададзена аўтар Amro, крыніца
Чытайце на EPS .
дададзена аўтар Mike DeSimone, крыніца
5.498 + 0.001 = анс 5,499000000000001 правільны адказ павінен быць 5.499
дададзена аўтар James Do, крыніца

5 адказы

Aabaz і Джым Клэй маюць добрыя тлумачэння таго, што адбываецца.

It's often the case that, rather than exactly calculating the value of 2*0.04 - 0.5*0.4^2, what you really want is to check whether 2*0.04 and 0.5*0.4^2 differ by an amount that is small enough to be within the relevant numerical precision. If that's the case, than rather than checking whether 2*0.04 - 0.5*0.4^2 == 0, you can check whether abs(2*0.04 - 0.5*0.4^2) < thresh. Here thresh can either be some arbitrary smallish number, or an expression involving eps, which gives the precision of the numerical type you're working with.

EDIT: Дзякуючы Джыму і Tal для прапанаванага ўдасканалення. Зменены параўнаць абсалютная значэнне рознасці з парогавым значэннем, а не розніца.

4
дададзена
Добрае пытанне. Адно змяненне я хацеў бы зрабіць тое, што вам трэба параўнаць абсалютная значэнне рознасці ў «малаціць».
дададзена аўтар Jim Clay, крыніца

Matlab выкарыстоўвае колькасці з якая плавае кропкай двайны дакладнасці для захоўвання сапраўдных лікаў. Гэтыя лікі выгляду т * 2 ^ е , дзе т ўяўляе сабой цэлы лік паміж 2 ^ 52 і 2 ^ 53 (далей мантисса ) і е гэта паказчык. Давайце назавем лік лік з якая плавае кропкай, калі яна мае такі выгляд.

Усе нумары, якія выкарыстоўваюцца ў разліках павінны быць лікамі з якая плавае кропкай. Часта гэта можа быць зроблена ў дакладнасці, як і 2 і 0.5 у гэтым выразе. Але для іншых лікаў, у першую чаргу большасць лікаў з лічбамі пасля дзесятковай кропкі, гэта не ўяўляецца магчымым, і набліжэнне павінна быць выкарыстана. Што адбываецца ў гэтым выпадку з'яўляецца тое, што колькасць акругляецца да бліжэйшага колькасці з якая плавае кропкай.

So, whenever you write something like 0.04 in Matlab, you're really saying "Get me the floating-point number that is closest to 0.04. In your expression, there are 2 numbers that need to be approximated: 0.04 and 0.4.

Акрамя таго, дакладны вынік аперацый, такія як складанне і множанне лікаў з якая плавае кропкай не можа быць лікам з якая плавае кропкай. Нягледзячы на ​​тое, што заўсёды ў форме т * 2 ^ е мантисса можа быць занадта вялікім. Такім чынам, вы атрымліваеце дадатковую хібнасць ад акруглення вынікаў аперацый.

У рэшце рэшт, просты выраз, як у вас будзе адключана ад каля 2 ^ -52 раз памеру аперанд, або каля 10 ^ -17.

У заключэнні: прычына ваша выраз ня вылічаецца нуль два разы:

  1. Некаторыя з нумароў вы пачынаеце з розныя (набліжэння) да дакладных лічбаў, прадастаўленым вамі.
  2. <�Літый> Прамежкавыя вынікі могуць быць таксама апраксімацыі дакладных вынікаў.
2
дададзена

Я не ведаю, калі гэта дастасавальна да вашай праблеме, але часта самае простае рашэнне для маштабавання дадзеных.

Напрыклад:

a=0.04;
b=0.2;
a-0.2*b
ans=-6.9389e-018
c=a/min(abs([a b]));
d=b/min(abs([a b]));
c-0.2*d
ans=0

EDIT: of course I did not mean to give a universal solution to these kind of problems but it is still a good practice that can make you avoid a few problems in numerical computation (curve fitting, etc ...). See Jim Clay's answer for the reason why you are experiencing these problems.

1
дададзена
Ці ёсць прычына, што гэта працуе, ці гэта проста аднарангавыя код, які адбываецца, каб зрабіць «правільна» у дадзеным выпадку?
дададзена аўтар Oliver Charlesworth, крыніца
Я шчыра не ведаю, але гэта, безумоўна, ідзе ў правільным кірунку, каб вырашыць такога роду праблемы.
дададзена аўтар Aabaz, крыніца
Ці значыць гэта заўсёды працуе ці проста нейкі час?
дададзена аўтар Jim Clay, крыніца
Гэта не будзе працаваць заўсёды, як можна бачыць, спрабуючы е = @ (х) 1-х/х ^ 2 * х , а затым е (рандаў ()) некалькі раз. Часам гэта 0; часам гэта эпсілон. Маштабаванне дазваляе атрымаць лепшыя вынікі, але дакладнасць ўсё яшчэ ў эпсілон. Іншы варыянт заключаецца ў маштабе эпсілон, каб адпавядаць маштабе іншых значэнняў у задачы.
дададзена аўтар stardt, крыніца

Тое, што вы бачыце, з'яўляецца квантавання памылкі . Matlab выкарыстоўвае двайнікі для падання лікаў, і ў той час як яны здольныя шмат дакладнасці, яны да гэтага часу не могуць прадстаўляць ўсе сапраўдныя лікі, бо існуе безьліч сапраўдных лікаў. Я не ўпэўнены, што трук Aabaz, але ў цэлым я б сказаў, што гэта не ўсё, што вы можаце зрабіць, акрамя, магчыма, масажуючы свае ўваходы, каб быць падвойныя чыстыя нумары.

1
дададзена

Я ўпэўнены, што гэта той выпадак, Ye Olde пытанняў дакладнасці з якая плавае коскі.

Ці патрэбна 1E-17 дакладнасць? Ці з'яўляецца гэта проста выпадак жадання «даволі» выхад? У гэтым выпадку, вы можаце проста выкарыстоўваць фарматаваны Sprintf для адлюстравання колькасці ўважаецца лічбаў, якія вы хочаце.

Зразумейце, што гэта не праблема MATLAB, але фундаментальнае абмежаванне як лікі прадстаўляюцца ў двайковым выглядзе.

Для забавы, праца, што 0,1 у двайковым ...

Некаторыя спасылкі: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems http://www.mathworks.com/support/tech-notes/1100/1108.html

1
дададзена