මම වෙනත් විචල්‍යයකට පාවෙන පිටපතක් පිටපත් කළහොත් ඒවා සමාන වේද?


167

==පාවෙන ලක්ෂ්‍ය විචල්‍යයන්ගේ සමානාත්මතාවය පරීක්ෂා කිරීම භාවිතා කිරීම හොඳ ක්‍රමයක් නොවන බව මම දනිමි . නමුත් මට එය දැන ගැනීමට අවශ්‍ය වන්නේ පහත සඳහන් ප්‍රකාශ සමඟ ය:

float x = ...

float y = x;

assert(y == x)

සිට yපිටපත් කර ඇති බැවින් x, එම ප්‍රකාශය සත්‍යයක් වේද?


78
සැබෑ කේතය සහිත නිරූපණයකින් අසමානතාවය සැබවින්ම ඔප්පු කරන කෙනෙකුට මම 50 ක ත්‍යාගයක් ලබා දෙමි. මට අවශ්‍ය වන්නේ 80 එදිරිව 64 බිට් ක්‍රියාව ක්‍රියාත්මක වන ආකාරයයි. ජනනය කරන ලද එකලස් කිරීමේ කේතය පැහැදිලි කිරීම සඳහා තවත් 50 ක් එක් ලේඛනයක් තුළ ඇති අතර අනෙක් විචල්‍යය (හෝ අසමානතාවයට හේතුව කුමක් වුවත් එය පහත් මට්ටමකින් පැහැදිලි කිරීමට මා කැමතිය).
තෝමස් වෙල්ලර්

1
H තෝමස් වෙල්ලර් මේ පිළිබඳ GCC දෝෂය: gcc.gnu.org/bugzilla/show_bug.cgi?id=323 ; කෙසේ වෙතත්, මම එය x86-64 පද්ධතියක් මත අවවාද කිරීමට උත්සාහ කර ඇති අතර එය -Fast-math සමඟ පවා සිදු නොවේ. බිට් 32 පද්ධතියක් මත ඔබට පැරණි ජීසීසී එකක් අවශ්‍ය යැයි මම සැක කරමි.
pjc50

5
j pjc50: ඇත්ත වශයෙන්ම ඔබට දෝෂ 323 ප්‍රතිනිෂ්පාදනය කිරීමට බිට් 80 පද්ධතියක් අවශ්‍ය වේ; එය 80x87 FPU ය. x86-64 SSE FPU භාවිතා කරයි. අමතර බිටු ගැටළුව ඇති කරයි, මන්ද ඒවා බිටු 32 පාවෙන අගයකට විහිදෙන විට ඒවා වටකුරු ය.
MSalters

4
MSalters න්‍යාය නිවැරදි නම් (මම එය සැක කරමි), එවිට ඔබට 32-බිට් ( -m32) සඳහා සම්පාදනය කිරීමෙන් හෝ x87 FPU ( -mfpmath=387) භාවිතා කිරීමට GCC ට උපදෙස් දීමෙන් ඔබට අවවාද කළ හැකිය .
කෝඩි ග්‍රේ

4
"බිට් 48" "බිට් 80" ලෙස වෙනස් කරන්න, එවිට ඔබට එහි "මිථ්‍යා" නාම විශේෂණය ඉවත් කළ හැකිය, ot හොට්. ඔබේ අදහස් දැක්වීමට පෙර සාකච්ඡා කරනු ලැබුවේ එයයි. X87 (x86 ගෘහ නිර්මාණ ශිල්පය සඳහා FPU) බිට් 80 රෙජිස්ටර් භාවිතා කරයි, එය "දීර්-නිරවද්‍යතාව" ආකෘතියකි.
කෝඩි අළු

Answers:


125

assert(NaN==NaN);Kmdreko විසින් පෙන්වා දී ඇති නඩුවට අමතරව , ඔබට x87-math සමඟ තත්වයන් ඇති විය හැකිය, 80bit පාවෙන තාවකාලිකව මතකයට ගබඩා කර පසුව ලේඛනයක් තුළ තවමත් ගබඩා කර ඇති අගයන් සමඟ සසඳන විට.

සම්පාදනය කිරීමේදී gcc9.2 සමඟ අසමත් විය හැකි අවම උදාහරණය -O2 -m32:

#include <cassert>

int main(int argc, char**){
    float x = 1.f/(argc+2);
    volatile float y = x;
    assert(x==y);
}

ගොඩ්බෝල්ට් නිරූපණය: https://godbolt.org/z/X-Xt4R

මෙම volatileඔබට ප්රමාණවත් ලේඛනය-පීඩනය ඇති නිර්මාණය කිරීමට කළමනාකරණය නම්, බොහෝ විට නොසලකා හරින හැකි yමතකය වෙතින් ගබඩා හා Reloaded (නමුත් සම්පාදකවරයා තරම් ව්යාකූල, සමස්ත-එකට සංසන්දනය පළමුෙවන් නැත).

GCC නිති අසන ප්‍රශ්න බලන්න:


2
floatසම්මත නිරවද්‍යතාවයකින් අතිරේක නිරවද්‍යතාව සමඟ සංසන්දනය කිරීමේදී අමතර බිටු සලකා බැලීම පුදුමයක් නොවේ .
Nat


13
H තෝමස් වෙල්ලර් නැත, එය සාධාරණ සම්මානයකි. මෙය අනුකූල නොවන හැසිරීමක් බව පෙන්වා දීමට මම පිළිතුරු දීමට කැමති වුවද
කක්ෂයේ සැහැල්ලු රේස්

4
එකලස් කිරීමේ කේතයේ හරියටම සිදුවන්නේ කුමක්ද යන්න පෙන්වා දෙමින් මට මෙම පිළිතුර දීර් extend කළ හැකිය - මෙය ඇත්ත වශයෙන්ම ප්‍රමිතිය උල්ලං that නය කරයි - මම භාෂා නීති lawyer යෙකු ලෙස නොකියුවත්, අපැහැදිලි නොවන බවට මට සහතික විය නොහැක එම හැසිරීමට පැහැදිලිවම ඉඩ දෙන වගන්තිය. මම සිතන්නේ OP සත්‍ය වශයෙන්ම සම්පාදකයින්ගේ ප්‍රායෝගික සංකූලතා කෙරෙහි වැඩි උනන්දුවක් දැක්වූයේ මිස සම්පූර්ණයෙන්ම දෝෂ රහිත, සම්පුර්ණයෙන්ම අනුකූල වූ සම්පාදකයින් මත නොවේ (ඒවා සත්‍ය වශයෙන්ම නොපවතින බව මම අනුමාන කරමි).
chtz

4
-ffloat-storeමෙය වලක්වා ගත හැකි මාර්ගය ලෙස සඳහන් කිරීම වටී .
OrangeDog

116

එය නම් සැබෑ වනු ඇත xයනු NaNමත සැසඳීම් සිට, NaNහැම විටම බොරු (ඔව්, පවා NaN == NaN). අනෙක් සියලුම අවස්ථාවන් සඳහා (සාමාන්‍ය අගයන්, අසාමාන්‍ය අගයන්, අනන්තය, ශුන්‍ය) මෙම ප්‍රකාශය සත්‍ය වනු ඇත.

පාවෙන ලක්ෂ්‍ය සංඛ්‍යා ගණිත ප්‍රකාශනවල භාවිතා කරන විට හරියටම බොහෝ ප්‍රති results ල ප්‍රකාශ කිරීමට නොහැකි වීම නිසා පාවෙන වළක්වා ගැනීම ==සඳහා වන උපදෙස් ගණනය කිරීම් වලට අදාළ වේ . පැවරුම ගණනය කිරීමක් නොවන අතර පැවරුම මුල් පිටපතට වඩා වෙනස් අගයක් ලබා දෙන බවට කිසිදු හේතුවක් නැත.


ප්‍රමිතිය අනුගමනය කරන්නේ නම් දීර් extended- නිරවද්‍යතා ඇගයීම ගැටලුවක් නොවිය යුතුය. <cfloat>සී [5.2.4.2.2.8] වෙතින් උරුම වූ ( අවධාරණය මගේ ):

පැවරුම් සහ වාත්තු කිරීම හැරුණු විට (සියලු අමතර පරාසය හා නිරවද්‍යතාව ඉවත් කරන) , සුපුරුදු ගණිත පරිවර්තනයන්ට සහ පාවෙන නියතයන්ට යටත්ව පාවෙන මෙහෙයුම් සහ අගයන් සහිත මෙහෙයුම් වල අගයන් ඇගයීමට ලක් කරනු ලබන්නේ අවශ්‍ය පරාසය හා නිරවද්‍යතාවය අවශ්‍ය ප්‍රමාණයට වඩා වැඩි විය හැකි ආකෘතියකට ය. වර්ගය.

කෙසේ වෙතත්, අදහස් පෙන්වා දී ඇති පරිදි, සමහර සම්පාදකයින්, ගොඩනැඟීමේ විකල්ප සහ ඉලක්ක සහිත සමහර අවස්ථා මෙය පරස්පර විරෝධී ලෙස අසත්‍යයක් බවට පත් කළ හැකිය .


10
නම් කුමක් xසඳහා අවම වඩා නිරවද්යතාව අනුව, ප්රථම අනුකූලව ලේඛනයේ ගණනය කරන්නේ float. මෙම y = xපමණක් තබා ගනිමින්, මතකයේ විය හැකි floatනිරවද්යතාව. එවිට සමානාත්මතාවය සඳහා වන පරීක්ෂණය ලේඛනයට එරෙහි මතකය, විවිධ නිරවද්‍යතාවන් සමඟ සිදු කෙරෙන අතර එමඟින් කිසිදු සහතිකයක් නොමැත.
ඩේවිඩ් ෂ්වාට්ස්

5
x+pow(b,2)==x+pow(a,3)ඊට වඩා වෙනස් auto one=x+pow(b,2); auto two=y+pow(a,3); one==twoවිය හැක්කේ යමෙකු අනෙකට වඩා නිරවද්‍යතාවයකින් සංසන්දනය කළ හැකි බැවිනි (එකක් / දෙකක් බැටරියේ බිට් 64 අගයන් නම්, අතරමැදි අගයන් fpu හි බිටු 80ish වේ). ඒ නිසා පැවරුමට යමක් කළ හැකිය, සමහර විට.
යක් - ඇඩම් නෙව්රාමොන්ට්

22
ෂුවර්! මගේ පිළිතුර ප්‍රමිතිය අනුගමනය කරයි. විශේෂයෙන් වේගවත් ගණිතය සක්‍රීය කිරීමේදී ඔබේ සම්පාදකයාට අවුල් සහගත නොවන ලෙස පැවසුවහොත් සියලු ඔට්ටු අක්‍රීය වේ.
kmdreko

11
මගේ පිළිතුරේ උපුටා දැක්වීම බලන්න. RHS හි අගය LHS හි විචල්‍යයට පවරා ඇත. LHS හි ප්‍රති value ලයක් ලෙස RHS හි වටිනාකමට වඩා වෙනස් වීමට නීතිමය සාධාරණීකරණයක් නොමැත. සම්පාදකයින් කිහිප දෙනෙකුට මේ සම්බන්ධයෙන් දෝෂ ඇති බව මම අගය කරමි. නමුත් යමක් ලේඛනයක ගබඩා කර තිබේද යන්නට කිසිදු සම්බන්ධයක් නැත.
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

6
OoVoo: ISO C ++ හි, පළල ටයිප් කිරීමට වටය ඕනෑම පැවරුමකදී සිදුවිය යුතුය. X87 ඉලක්ක කරන බොහෝ සම්පාදකයින් තුළ, එය සැබවින්ම සිදුවන්නේ සම්පාදකයා විසිරී / නැවත පූරණය කිරීමට තීරණය කළ විට පමණි. gcc -ffloat-storeදැඩි අනුකූලතාවයක් සඳහා ඔබට එය බල කළ හැකිය. නමුත් මෙම ප්‍රශ්නය x=y; x==y; එකිනෙකට වෙනස් වීමට කිසිවක් නොකර සිටීමයි. පාවෙන තැනකට සරිලන සේ දැනටමත් වටකුරු කර ඇත්නම් y, ද්විත්ව හෝ දිගු ද්විත්ව සහ පසුපසට පරිවර්තනය කිරීමෙන් වටිනාකම වෙනස් නොවේ. ...
පීටර් කෝර්ඩ්ස්

34

ඔව්, yමෙහි වටිනාකම නිසැකවම ගනු ඇත x:

[expr.ass]/2: සරල පැවරුමකදී (=), වම් ඔපෙරන්ඩ් විසින් යොමු කරන ලද වස්තුව නව ක්‍රියාකාරිත්වයේ ප්‍රති result ලය සමඟ එහි අගය ප්‍රතිස්ථාපනය කිරීමෙන් වෙනස් කරනු ලැබේ ([defns.access]).

වෙනත් අගයන් පැවරීමට ඉඩක් නොමැත.

(අනෙක් අය දැනටමත් පෙන්වා දී ඇත්තේ සමානතා සැසඳීමක් ==කෙසේ වෙතත් falseNaN අගයන් සඳහා තක්සේරු කරනු ඇති බවයි.)

පාවෙන ලක්ෂ්‍යය සමඟ ඇති සාමාන්‍ය ගැටළුව නම්, ඔබ සිතන තරම් වටිනාකමක් නොතිබීම== පහසුය . මෙහිදී, සාරධර්ම දෙක, ඒවා කුමක් වුවත්, එක සමාන බව අපි දනිමු.


7
H තෝමස් වෙල්ලර් එය අනුකූල නොවන ක්‍රියාවට නැංවීමේදී දන්නා දෝෂයකි. එය සඳහන් කිරීම සතුටක්!
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

මුලදී, මම සිතුවේ “අගය” සහ “ප්‍රති result ලය” අතර වෙනස නීතිගත කිරීම විකෘති වනු ඇති බවයි, නමුත් මෙම වෙනස C2.2, 7.1.6 භාෂාවෙන් වෙනසකින් තොරව අවශ්‍ය නොවේ; සී 3.3, 7.1.6; ඔබ උපුටා දක්වන සම්මත කෙටුම්පතේ C4.2, 7.1.6, හෝ C5.3, 7.1.6.
එරික් ටවර්ස්

Ric එරික් ටවර්ස් කණගාටුයි ඔබට එම යොමු කිරීම් පැහැදිලි කළ හැකිද? ඔබ යොමු කරන්නේ කුමක්දැයි මම සොයා
නොගත්තෙමි

@ LightnessRacesBY-SA3.0: සී . C2.2 , C3.3 , C4.2 සහ C5.3 .
එරික් ටවර්ස්

Ric එරික් ටවර්ස් ඔව්, තවමත් ඔබ පසුපස යන්නේ නැත. ඔබගේ පළමු සබැඳිය උපග්‍රන්ථ සී දර්ශකයට යයි (මට කිසිවක් නොකියයි). ඔබගේ ඊළඟ සබැඳි හතර වෙත යන්න [expr]. මම සබැඳි නොසලකා හැර උපුටා දැක්වීම් කෙරෙහි අවධානය යොමු කළහොත්, උදා: C.5.3 "අගය" යන පදය හෝ " ප්‍රති result ලය " යන යෙදුම ආමන්ත්‍රණය කරන බවක් නොපෙනේ. එහි සාමාන්‍ය ඉංග්‍රීසි සන්දර්භයට වරක් "ප්‍රති result ලය" භාවිතා කරන්න). සමහර විට ඔබට ප්‍රමිතිය වෙනසක් කරයි කියා ඔබ සිතන තැන වඩාත් පැහැදිලිව විස්තර කළ හැකි අතර මෙය සිදුවීමට පැහැදිලි උපුටා දැක්වීමක් ලබා දිය හැකිය. ස්තූතියි!
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

3

ඔව්, සෑම අවස්ථාවකම (NaNs සහ x87 ගැටළු නොසලකා හැරීම) මෙය සත්‍ය වනු ඇත.

ඔබ ඒවා ගැන යමක් කළහොත් ඔබට memcmpNaNs සහ sNaNs සංසන්දනය කිරීමට හැකි වන අතර සමානාත්මතාවය සඳහා පරීක්‍ෂා කළ හැකිය. මේ සඳහා සම්පාදකයාට විචල්‍යයේ ලිපිනය ගැනීමට අවශ්‍ය වන අතර එමඟින් අගය float80-බිට් එකක් වෙනුවට 32-බිට් බවට බල කෙරේ . මෙය x87 ගැටළු ඉවත් කරනු ඇත. මෙහි දෙවන ප්‍රකාශය ==NaNs සත්‍ය ලෙස සැසඳිය නොහැකි බව පෙන්වීමට අසමත් වීම අරමුණු කර ගෙන ඇත:

#include <cmath>
#include <cassert>
#include <cstring>

int main(void)
{
    float x = std::nan("");
    float y = x;
    assert(!std::memcmp(&y, &x, sizeof(float)));
    assert(y == x);
    return 0;
}

NaNs වලට වෙනස් අභ්‍යන්තර නිරූපණයක් තිබේ නම් (එනම් වෙනස් මැන්ටිස්සා), memcmpසත්‍යය සැසඳෙන්නේ නැත.


1

සුපුරුදු අවස්ථාවන්හිදී, එය සත්‍ය ලෙස තක්සේරු කරනු ඇත. (හෝ ප්‍රකාශ ප්‍රකාශය කිසිවක් නොකරනු ඇත)

සංස්කරණය කරන්න :

'සුපුරුදු අවස්ථා' මගින් මා අදහස් කරන්නේ ඉහත සඳහන් කළ අවස්ථා (NaN අගයන් සහ 80x87 පාවෙන ලක්ෂ්‍ය ඒකක වැනි) වෙනත් පරිශීලකයින් විසින් පෙන්වා දී ඇති පරිදි බැහැර කිරීමයි.

වර්තමාන සන්දර්භය තුළ චිප්ස් 8087 යල් පැන යාම සැලකිල්ලට ගෙන, ගැටළුව තරමක් හුදෙකලා වී ඇති අතර ප්‍රශ්නය පාවෙන ලක්ෂ්‍ය ගෘහ නිර්මාණ ශිල්පයේ වර්තමාන තත්වයට අදාළ වේ.

(යොමු කිරීම 8087 - https://home.deec.uc.pt/~jlobo/tc/artofasm/ch14/ch143.htm )

හොඳ ආදර්ශයක් ප්‍රතිනිෂ්පාදනය කිරීම සඳහා කුඩෝස් සිට @chtz දක්වාත්, NaNs සඳහන් කිරීම සඳහා mkmdreko - ඔවුන් ගැන මීට පෙර දැන සිටියේ නැත!


1
මතකයෙන් පටවන xඅතරතුර පාවෙන ස්ථාන ලේඛනයක සිටීම සම්පූර්ණයෙන්ම කළ හැකි යැයි මම සිතුවෙමි y. මතකය ලේඛනයකට වඩා අඩු නිරවද්‍යතාවයක් තිබිය හැකි අතර එය සංසන්දනය අසාර්ථක වේ.
ඩේවිඩ් ෂ්වාට්ස්

1
එය අසත්‍යයක් සඳහා එක් අවස්ථාවක් විය හැකිය, මම එතරම් දුරට සිතුවේ නැත. (OP විසින් විශේෂ අවස්ථා කිසිවක් ලබා දී නොමැති බැවින්, මම අතිරේක බාධක කිසිවක් උපකල්පනය
නොකරමි

1
මට ඇත්තටම තේරෙන්නේ නැහැ ඔයා කියන දේ. මම ප්‍රශ්නය තේරුම් ගත් පරිදි, OP විමසන්නේ පාවෙන පිටපතක් පිටපත් කර සමානාත්මතාවය සඳහා වන පරීක්ෂණය සාර්ථක වනු ඇත්ද යන්නයි. ඔබේ පිළිතුර "ඔව්" යැයි පවසන බවක් පෙනේ. මම අහනවා ඇයි පිළිතුර නැත්තේ කියලා.
ඩේවිඩ් ෂ්වාට්ස්

6
සංස්කරණය මෙම පිළිතුර වැරදිය. C ++ ප්‍රමිතියට අනුව පැවරුම අගය ගමනාන්ත වර්ගයට පරිවර්තනය කිරීම අවශ්‍ය වේ expression අතිරික්ත නිරවද්‍යතාවය ප්‍රකාශන ඇගයීම් සඳහා භාවිතා කළ හැකි නමුත් පැවරුම මඟින් එය රඳවා නොගනී. වටිනාකම ලේඛනයක හෝ මතකයේ තිබේද යන්න වැදගත් නැත; C ++ ප්‍රමිතියට එය අවශ්‍ය වන්නේ කේතය ලියා ඇති පරිදි floatඅමතර නිරවද්‍යතාවයකින් තොර අගයක් ලෙස ය.
එරික් පෝස්ට්පිස්ල්

2
Ro ප්‍රෝග්‍රැමර් (n අතිශයින්ම දෝෂ සහිත සම්පාදකයෙකු න්‍යායාත්මකව int a=1; int b=a; assert( a==b );ප්‍රකාශයක් කිරීමට හේතු විය හැකි බැවින්, නිවැරදිව ක්‍රියාත්මක වන සම්පාදකයෙකු සම්බන්ධයෙන් මෙම ප්‍රශ්නයට පිළිතුරු සැපයීම අර්ථවත් යැයි මම සිතමි (සමහර සම්පාදකයින්ගේ සමහර සංස්කරණවල / ඇති -බීන්-දන්නා-මෙය වැරදියට තේරුම් ගැනීමට). ප්‍රායෝගිකව ගත් කල, කිසියම් හේතුවක් නිසා සම්පාදකයෙකු ලේඛනයේ ගබඩා කළ පැවරුමක ප්‍රති result ලයෙන් අමතර නිරවද්‍යතාව ඉවත් නොකරන්නේ නම්, එය එම අගය භාවිතා කිරීමට පෙර එය කළ යුතුය.
ට්‍රයිප්හවුන්ඩ්

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.