පහත කේතය සලකා බලන්න:
0.1 + 0.2 == 0.3 -> false
0.1 + 0.2 -> 0.30000000000000004
මෙම සාවද්යතාවයන් සිදුවන්නේ ඇයි?
පහත කේතය සලකා බලන්න:
0.1 + 0.2 == 0.3 -> false
0.1 + 0.2 -> 0.30000000000000004
මෙම සාවද්යතාවයන් සිදුවන්නේ ඇයි?
Answers:
ද්විමය පාවෙන ලක්ෂ්ය ගණිතය මේ වගේ ය. බොහෝ ක්රමලේඛන භාෂාවල එය IEEE 754 ප්රමිතිය මත පදනම් වේ . ගැටළුවේ හරය නම්, මෙම ආකෘතියෙන් සංඛ්යා නිරූපණය වන්නේ මුළු සංඛ්යාව මෙන් දෙගුණයක බලයක් ලෙස ය; පරිමේය සංඛ්යා ලෙස ( 0.1
වන, 1/10
) තම හරය හරියටම නිරූපනය කළ නොහැක දෙකක බලය නෙවෙයි.
සඳහා 0.1
සම්මත දී binary64
ආකෘතිය එම නිරූපණය හරියටම ලෙස ලිවිය හැකි
0.1000000000000000055511151231257827021181583404541015625
දශමයෙන් හෝ0x1.999999999999ap-4
දී C99 ප්රමිතියේ දී අංකනය hexfloat .ඊට වෙනස්ව, තාර්කික අංකය 0.1
, එනම් 1/10
හරියටම ලිවිය හැකිය
0.1
දශමයෙන් හෝ0x1.99999999999999...p-4
C99 හෙක්ස්ෆ්ලෝට් අංකනයෙහි ප්රතිසමයක් තුළ, ...
9 හි නිමක් නැති අනුක්රමයක් නිරූපණය කරයි.නියතයන් 0.2
සහ 0.3
ඔබේ වැඩසටහනේ ඒවායේ සත්ය අගයන් සඳහා ආසන්න අගයන් වේ. එය සමීපතම එය සිදු double
කිරීමට 0.2
මෙම පරිමේය සංඛ්යාවක් වඩා විශාල වන අතර, 0.2
නමුත් සමීපතම බව double
සඳහා 0.3
වූ තර්කානුකූල සංඛ්යාවට වඩා කුඩා වන 0.3
. එකතුව 0.1
සහ 0.2
සුළං තාර්කික සංඛ්යාවට වඩා විශාල වන 0.3
අතර එම නිසා ඔබේ කේතයේ නියතයට එකඟ නොවේ.
පාවෙන ලක්ෂ්ය අංක ගණිතය පිළිබඳ සෑම පරිගණක විද්යා ient යෙක්ම දැනගත යුතු දේ නම් පාවෙන ලක්ෂ්ය අංක ගණිතමය ගැටළු සඳහා තරමක් පුළුල් ප්රතිකාරයකි . පහසුවෙන් ජීර්ණය කළ හැකි පැහැදිලි කිරීමක් සඳහා, floating-point-gui.de බලන්න .
පැති සටහන: සියලුම ස්ථානීය (පාදක-එන්) සංඛ්යා පද්ධති මෙම ගැටළුව නිරවද්යතාවයෙන් බෙදා ගනී
සරල පැරණි දශම (පදනම් 10) ඉලක්කම් වලට එකම ගැටළු ඇත, එබැවින් 1/3 වැනි සංඛ්යා 0.333333333 ලෙස අවසන් වේ ...
ඔබ දශම පද්ධතිය සමඟ නිරූපණය කිරීම පහසු වන (3/10) අංකයකට පැකිලී ඇත, නමුත් ද්විමය පද්ධතියට නොගැලපේ. එය දෙයාකාරයෙන්ම (තරමක් දුරට) ගමන් කරයි: 1/16 යනු දශමයෙන් (0.0625) කැත සංඛ්යාවක් වන නමුත් ද්විමය වශයෙන් එය දශමයෙන් (0.0001) 10,000 වැනි ප්රමාණයට වඩා පිළිවෙලට පෙනේ ** - අප සිටියේ නම් අපගේ එදිනෙදා ජීවිතයේදී බේස් -2 අංක පද්ධතියක් භාවිතා කිරීමේ පුරුද්ද, ඔබ එම අංකය දෙස බලා යම් දෙයක් අඩකින්, නැවත අඩකින් හා නැවත නැවතත් කිරීමෙන් ඔබට එහි පැමිණිය හැකි බව සහජයෙන්ම තේරුම් ගනී.
** ඇත්ත වශයෙන්ම, පාවෙන ලක්ෂ්ය සංඛ්යා මතකයේ ගබඩා වන්නේ හරියටම නොවේ (ඔවුන් විද්යාත්මක අංකන ක්රමයක් භාවිතා කරයි). කෙසේ වෙතත්, ද්විමය පාවෙන ලක්ෂ්ය නිරවද්යතා දෝෂයන් වර්ධනය වීමට නැඹුරු වන කාරණය එයින් පැහැදිලි වේ, මන්ද අප සාමාන්යයෙන් වැඩ කිරීමට උනන්දුවක් දක්වන “තාත්වික ලෝකය” සංඛ්යා බොහෝ විට දස දෙනෙකුගේ බලයන් වන නමුත් අප දශම සංඛ්යා පද්ධතියක් භාවිතා කරන නිසා පමණි- අද. "සෑම 7 න් 5 ක්" වෙනුවට 71% වැනි දේ අපි කියන්නේ මේ නිසාය (71% යනු ආසන්න අගයකි, 5/7 කිසිදු දශම සංඛ්යාවක් සමඟ හරියටම නිරූපණය කළ නොහැකි බැවින්).
එබැවින් නැත: ද්විමය පාවෙන ලක්ෂ්ය සංඛ්යා කැඩී නැත, ඒවා අනෙක් සෑම පදනම්-එන් සංඛ්යා පද්ධතියක් මෙන් අසම්පූර්ණ වනු ඇත :)
පැති පැත්ත සටහන: ක්රමලේඛනයේ පාවෙන සමඟ වැඩ කිරීම
ප්රායෝගිකව, මෙම නිරවද්යතාවයේ ගැටළුව නම්, ඔබේ පාවෙන ලක්ෂ්ය සංඛ්යා ප්රදර්ශනය කිරීමට පෙර ඔබ උනන්දුවක් දක්වන දශම ස්ථාන ගණනකට රවුම් කිරීමට වටකුරු ශ්රිත භාවිතා කළ යුතු බවයි.
සමානාත්මතා පරීක්ෂණ යම් තරමකට ඉවසීමට ඉඩ දෙන සැසඳීම් සමඟ ප්රතිස්ථාපනය කිරීමට ඔබට අවශ්යය, එයින් අදහස් වන්නේ:
එපා නොවන කරන්නif (x == y) { ... }
ඒ වෙනුවට කරන්න if (abs(x - y) < myToleranceValue) { ... }
.
abs
නිරපේක්ෂ වටිනාකම කොහේද ? myToleranceValue
ඔබගේ විශේෂිත යෙදුම සඳහා තෝරා ගත යුතුය - තවද එයට ඔබ කොපමණ "විග්ල් කාමරයක්" ඉඩ දීමට සූදානම්ද යන්නත්, ඔබ සැසඳීමට යන විශාලතම සංඛ්යාව කුමක් ද යන්නත් බොහෝ දේ ඇත (නිරවද්යතා ගැටළු නැතිවීම හේතුවෙන්) ). ඔබ කැමති භාෂාවෙන් "එප්සිලන්" විලාසිතාවේ නියතයන්ගෙන් පරිස්සම් වන්න. මේවා ඉවසීමේ අගයන් ලෙස භාවිතා නොකළ යුතුය.
මම පාවෙන ලක්ෂ්ය දෘඩාංග නිර්මාණය කර ගොඩනඟන බැවින් දෘඩාංග නිර්මාණකරුවෙකුගේ ඉදිරිදර්ශනය මෙයට එක් කළ යුතු යැයි මම විශ්වාස කරමි. දෝෂයේ මූලාරම්භය දැන ගැනීම මෘදුකාංගයේ සිදුවන්නේ කුමක්ද යන්න තේරුම් ගැනීමට උපකාරී වනු ඇති අතර, අවසානයේදී, පාවෙන ලක්ෂ්ය දෝෂ සිදුවීමට හේතු සහ කාලයත් සමඟ සමුච්චය වීමට හේතු පැහැදිලි කිරීමට මෙය උපකාරී වනු ඇතැයි මම බලාපොරොත්තු වෙමි.
ඉංජිනේරු දෘෂ්ටි කෝණයකින් බලන විට, පාවෙන ලක්ෂ්ය ගණනය කිරීම් සිදුකරන දෘඩාංග සඳහා අවශ්ය වන්නේ අවසාන ස්ථානයේ එක් ඒකකයකින් අඩකටත් වඩා අඩු දෝෂයක් තිබීමයි. එමනිසා, බොහෝ දෘඩාංග නිරවද්යතාවයෙන් නතර වනු ඇත්තේ පාවෙන ලක්ෂ්ය බෙදීමේදී විශේෂයෙන් ගැටළු සහගත වන එක් මෙහෙයුමක් සඳහා අවසාන ස්ථානයේ එක් ඒකකයකින් අඩකටත් වඩා අඩු දෝෂයක් ලබා දීමට පමණි . තනි මෙහෙයුමක් යනු කුමක්ද යන්න රඳා පවතින්නේ ඒකකය කොපමණ මෙහෙයුම් ප්රමාණයක් ගත යුතුද යන්න මතය. බොහෝ දෙනෙකුට එය දෙකක් වේ, නමුත් සමහර ඒකක මෙහෙයුම් 3 ක් හෝ වැඩි ගණනක් ගනී. මේ නිසා, කාලයත් සමඟ දෝෂ එකතු වන බැවින් නැවත නැවත ක්රියාත්මක කිරීම ප්රිය දෝෂයක් බවට සහතිකයක් නොමැත.
බොහෝ ප්රොසෙසරයන් IEEE-754 ප්රමිතිය අනුගමනය කරන නමුත් සමහර ඒවා අවලංගු කරන ලද හෝ වෙනස් ප්රමිතීන් භාවිතා කරයි. නිදසුනක් ලෙස, නිරවද්යතාවයේ වියදමින් ඉතා කුඩා පාවෙන ලක්ෂ්ය සංඛ්යා නිරූපණය කිරීමට ඉඩ සලසන IEEE-754 හි අවලංගු කරන ලද මාදිලියක් ඇත. කෙසේ වෙතත්, පහත දැක්වෙන්නේ සාමාන්ය මෙහෙයුම් ක්රමය වන IEEE-754 සාමාන්යකරණය කළ ආකාරයයි.
IEEE-754 ප්රමිතියේ දී, දෘඩාංග නිර්මාණකරුවන්ට දෝෂ / එප්සිලෝන් වල ඕනෑම අගයක් අවසාන ස්ථානයේ එක් ඒකකයකින් අඩකටත් වඩා අඩු වන තාක් කල් ඉඩ දී ඇති අතර ප්රති result ලය තිබිය යුත්තේ අන්තිම ඒකකයේ භාගයකට වඩා අඩු විය යුතුය. එක් මෙහෙයුමක් සඳහා ස්ථානය. නැවත නැවත මෙහෙයුම් සිදු වන විට දෝෂ එකතු වීමට හේතුව මෙයින් පැහැදිලි වේ. IEEE-754 ද්විත්ව නිරවද්යතාව සඳහා, මෙය 54 වන බිට් වේ, මන්ද පාවෙන ලක්ෂ්ය අංකයේ (උදා: 5.3e5 හි 5.3) සංඛ්යාත්මක කොටස (සාමාන්යකරණය), මැන්ටිස්සා ලෙසද හැඳින්වීමට බිටු 53 භාවිතා කරයි. විවිධ පාවෙන ස්ථාන මෙහෙයුම් වලදී දෘඩාංග දෝෂ ඇතිවීමට හේතු පිළිබඳව ඊළඟ කොටස් වඩාත් සවිස්තරාත්මකව සොයා බලයි.
පාවෙන ලක්ෂ්ය බෙදීමේ දෝෂයට ප්රධාන හේතුව වන්නේ ගණනය කිරීම සඳහා භාවිතා කරන බෙදීම් ඇල්ගොරිතමයි. බොහෝ පරිගණක පද්ධති ප්රතිලෝමයකින් ගුණ කිරීම මගින් බෙදීම ගණනය කරයි, ප්රධාන වශයෙන් Z=X/Y
,Z = X * (1/Y)
. බෙදීමක් නැවත ගණනය කරනු ලැබේ, එනම් සෑම චක්රයක්ම අපේක්ෂිත නිරවද්යතාව ළඟා වන තෙක් ප්රමාණයේ බිටු ගණනය කරයි, IEEE-754 සඳහා අවසාන ස්ථානයේ ඒකක එකකට වඩා අඩු දෝෂයක් ඇත. Y (1 / Y) හි පරස්පරතා වගුව මන්දගාමී කොට් in ාශයේ ප්රමාණාත්මක තේරීම් වගුව (QST) ලෙස හැඳින්වෙන අතර, ප්රමාණාත්මක තේරීම් වගුවේ බිටු වල ප්රමාණය සාමාන්යයෙන් රේඩික්ස් පළල හෝ බිටු ගණනාවක් වේ. එක් එක් පුනරාවර්තනයේ දී ගණනය කරන ලද උපුටා ගැනීම සහ ආරක්ෂක බිටු කිහිපයක්. IEEE-754 ප්රමිතිය සඳහා, ද්විත්ව නිරවද්යතාව (64-බිට්), එය බෙදුම්කරුගේ රේඩික්ස් ප්රමාණය හා ආරක්ෂක බිටු කිහිපයක් k, කොහේද k>=2
. උදාහරණයක් ලෙස, වරකට බිටු 2 ක් (රේඩික්ස් 4) ගණනය කරන බෙදුම්කරුවෙකු සඳහා සාමාන්ය ප්රමාණාත්මක තේරීම් වගුව 2+2= 4
බිටු (විකල්ප විකල්ප බිටු කිහිපයක් ) වනු ඇත .
3.1 කොට් round ාශ වටකුරු දෝෂය: පරස්පරතා ආසන්න කිරීම
උපුටා දැක්වීමේ තේරීම් වගුවේ ඇති පරස්පරතා බෙදීම් ක්රමය මත රඳා පවතී : SRT අංශය වැනි මන්දගාමී බෙදීම හෝ ගෝල්ඩ්ස්මිඩ්ට් අංශය වැනි වේගවත් බෙදීම; සෑම ප්රවේශයක්ම බෙදීම් ඇල්ගොරිතම අනුව වෙනස් කරනුයේ හැකි අවම දෝෂයක් ලබා දීමටය. කෙසේ වෙතත්, සියලු පරස්පරතා ආසන්න වශයෙන් දැක්වේසත්ය පරස්පරයේ සහ දෝෂයේ යම් අංගයක් හඳුන්වා දෙන්න. මන්දගාමී බෙදීම් සහ වේගවත් බෙදීම් ක්රම දෙකම සංඛ්යාත්මකව නැවත ගණනය කරයි, එනම්, එක් එක් පියවරේ බිටු කිහිපයක් ගණනය කරනු ලැබේ, ඉන්පසු ප්රති result ලය ලාභාංශයෙන් අඩු කරනු ලැබේ, සහ දෝෂය එකෙන් අඩකටත් වඩා අඩු වන තෙක් බෙදුම්කරු පියවර නැවත කරයි. ඒකකය අවසාන ස්ථානයේ. මන්දගාමී බෙදීම් ක්රම මඟින් සෑම පියවරකදීම සංඛ්යාංකයේ නිශ්චිත සංඛ්යාවක් ගණනය කරනු ලබන අතර ඒවා සෑදීමට සාමාන්යයෙන් අඩු වියදම් වන අතර වේගවත් බෙදීම් ක්රම මඟින් පියවරකට විචල්ය සංඛ්යා සංඛ්යාවක් ගණනය කරන අතර ඒවා තැනීමට වඩා මිල අධික වේ. බෙදීම් ක්රමවල වැදගත්ම කොටස නම්, ඔවුන්ගෙන් බොහෝ දෙනෙක් පරස්පරයක් ආසන්න වශයෙන් ගණනය කිරීමෙන් නැවත නැවත ගුණ කිරීම මත රඳා සිටීමයි , එබැවින් ඒවා දෝෂ වලට ගොදුරු වේ.
සියළුම මෙහෙයුම් වල වටකුරු දෝෂ සඳහා තවත් හේතුවක් වන්නේ IEEE-754 ඉඩ දෙන අවසාන පිළිතුරේ විවිධ කප්පාදු කිරීමේ ක්රම වේ. කප්පාදු කිරීම, වටයේ සිට ශුන්යය, වටයේ සිට ළඟම (පෙරනිමිය), වටය-පහළට සහ වටය දක්වා ඇත. සියලුම ක්රම මඟින් එක් මෙහෙයුමක් සඳහා අවසාන ස්ථානයේ ඒකක එකකට වඩා අඩු දෝෂයක මූලද්රව්යයක් හඳුන්වා දෙයි. කාලයාගේ ඇවෑමෙන් සහ නැවත නැවත සිදුකරන මෙහෙයුම් වලදී, කප්පාදු කිරීම ද ප්රති result ල දෝෂයට සමුච්චිත ලෙස එකතු කරයි. On ාතීයකරණයේදී මෙම කප්පාදු කිරීමේ දෝෂය විශේෂයෙන් ගැටළු සහගත වන අතර, එය යම් ආකාරයක නැවත නැවත ගුණ කිරීමකට සම්බන්ධ වේ.
පාවෙන ලක්ෂ්ය ගණනය කිරීම් සිදුකරන දෘඩාංගයට අවශ්ය වන්නේ එක් මෙහෙයුමක් සඳහා අවසාන ස්ථානයේ එක් ඒකකයකින් අඩකටත් වඩා අඩු දෝෂයක් සහිත ප්රති result ලයක් ලබා දිය යුතු බැවින්, නරඹන්නේ නැතිනම් නැවත නැවත සිදුකරන මෙහෙයුම් වලදී දෝෂය වර්ධනය වේ. සීමිත දෝෂයක් අවශ්ය වන ගණනය කිරීම් වලදී, ගණිත ians යින් IEEE-754 හි අවසාන ස්ථානයේ වටකුරු සිට ආසන්නතම ඉලක්කම් භාවිතා කිරීම වැනි ක්රම භාවිතා කරයි , මන්ද, කාලයත් සමඟ දෝෂ එකිනෙකා අවලංගු වීමට වැඩි ඉඩක් ඇති බැවිනි. පිටත, සහ අන්තරාන්තර අංක ගණිතය IEEE 754 වටකුරු මාදිලිවල වෙනස්කම් සමඟ සංයුක්ත වේවටකුරු දෝෂ පුරෝකථනය කිරීමට සහ ඒවා නිවැරදි කිරීමට. අනෙකුත් වටකුරු මාතයන් හා සසඳන විට එහි අඩු සාපේක්ෂ දෝෂය නිසා, වටයේ සිට ආසන්නතම ඉලක්කම් දක්වා (අවසාන ස්ථානයේ), IEEE-754 හි පෙරනිමි වටකුරු මාදිලිය වේ.
පෙරනිමි වටකුරු මාදිලිය, වටකුරු සිට ආසන්නතම ඉලක්කම් පවා අවසාන ස්ථානයේ ඇති අතර, එක් මෙහෙයුමක් සඳහා අවසාන ස්ථානයේ එක් ඒකකයකින් අඩකටත් වඩා අඩු දෝෂයක් සහතික කරයි. කප්පාදු කිරීම, වටකුරු කිරීම සහ වටේට පහළට යාම පමණක් අවසාන ස්ථානයේ එක් ඒකකයකින් අඩකට වඩා වැඩි දෝෂයක් ඇති විය හැකි නමුත් අවසාන ස්ථානයේ එක් ඒකකයකට වඩා අඩුය, එබැවින් ඒවා නොමැති නම් මෙම මාතයන් නිර්දේශ නොකරයි අන්තරාන්තර අංක ගණිතයේ භාවිතා වේ.
කෙටියෙන් කිවහොත්, පාවෙන ලක්ෂ්ය මෙහෙයුම් වල දෝෂ සඳහා මූලික හේතුව වන්නේ දෘඩාංගවල කප්පාදු කිරීම හා බෙදීම සම්බන්ධයෙන් පරස්පරයක් කප්පාදු කිරීමයි. IEEE-754 ප්රමිතියට අවශ්ය වන්නේ එක් මෙහෙයුමක් සඳහා අවසාන ස්ථානයේ එක් ඒකකයකින් අඩකටත් වඩා අඩු දෝෂයක් පමණක් වන බැවින්, නිවැරදි නොකළහොත් නැවත නැවත සිදුකරන මෙහෙයුම්වල පාවෙන ලක්ෂ්ය දෝෂ එකතු වේ.
ඔබ 1 හෝ 1/10 පදනම් 2 (ද්විමය) බවට පරිවර්තනය කරන විට, දශම ලක්ෂ්යයෙන් පසු පුනරාවර්තන රටාවක් ඔබට ලැබෙනු ඇත, එනම් 10 වන පාදයේ 1/3 නිරූපණය කිරීමට උත්සාහ කරනවා සේම, අගය හරියටම නොවේ, එබැවින් ඔබට එය කළ නොහැක සාමාන්ය පාවෙන ලක්ෂ්ය ක්රම භාවිතා කරමින් ගණිතය.
මෙහි ඇති බොහෝ පිළිතුරු මෙම ප්රශ්නය ඉතා වියළි, තාක්ෂණික වචන වලින් ආමන්ත්රණය කරයි. සාමාන්ය මිනිසුන්ට තේරුම් ගත හැකි ආකාරයට මෙය ආමන්ත්රණය කිරීමට මම කැමතියි.
ඔබ පීසා කපා දැමීමට උත්සාහ කරන බව සිතන්න. ඔබට පීසා පෙති හරියටම අඩකින් කපා ගත හැකි රොබෝ පීසා කටර් ඇත. එය මුළු පීසා අඩකින් අඩක් කළ හැකිය, නැතහොත් පවතින පෙත්තක් අඩකින් අඩක් කළ හැකිය, නමුත් ඕනෑම අවස්ථාවක, අඩක් සෑම විටම නිරවද්ය වේ.
එම පීසා කටර් ඉතා සියුම් චලනයන් ඇති අතර, ඔබ සම්පූර්ණ පීසා සමඟ ආරම්භ කරන්නේ නම්, එය අඩකින් අඩු කර, සෑම විටම කුඩාම පෙත්ත අඩකින් අඩක් තබා ගන්න, පෙත්ත එහි ඉහළ නිරවද්යතා හැකියාවන් සඳහා පවා කුඩා වීමට පෙර 53 වතාවක් අඩක් කළ හැකිය. . එම අවස්ථාවේදී, ඔබට තවදුරටත් එම තුනී පෙත්තක් අඩකින් අඩක් කළ නොහැක, නමුත් එය ඇතුළත් කිරීම හෝ බැහැර කිරීම කළ යුතුය.
දැන්, පීසා එකෙන් දහයෙන් එකක් (0.1) හෝ පහෙන් එකක් (0.2) එකතු වන පරිදි ඔබ සියලු පෙති කැබලි කරන්නේ කෙසේද? ඇත්තටම ඒ ගැන සිතන්න, එය ක්රියාත්මක කිරීමට උත්සාහ කරන්න. ඔබ සතුව මිථ්යා නිරවද්ය පීසා කටර් එකක් තිබේ නම් ඔබට සැබෑ පීසා භාවිතා කිරීමට උත්සාහ කළ හැකිය. :-)
බොහෝ පළපුරුදු ක්රමලේඛකයින් ඇත්ත පිළිතුර දන්නවා, එනම් පීසා වලින් හරියටම දහයෙන් එකක් හෝ පහක් එකට එකතු කිරීමට ක්රමයක් නැති බව ය. ඔබට ඉතා හොඳ දළ විශ්ලේෂණයක් කළ හැකි අතර, ඔබ 0.2 ක ආසන්න අගයක් සමඟ 0.1 ක ආසන්න අගයක් එකතු කළහොත්, ඔබට 0.3 ක හොඳ ඇස්තමේන්තුවක් ලැබෙනු ඇත, නමුත් එය තවමත් එයමයි, දළ වශයෙන්.
ද්විත්ව නිරවද්යතා අංක සඳහා (ඔබේ පීසා 53 වතාවක් අඩකින් අඩු කිරීමට ඔබට ඉඩ සලසන නිරවද්යතාවය), 0.1 ට වඩා අඩු හා වැඩි සංඛ්යා 0.09999999999999999167332731531132594682276248931884765625 සහ 0.10000000000000000555111512312578225211225211 දෙවැන්න කලින් තිබූ ඒවාට වඩා 0.1 ට වඩා මඳක් ආසන්න ය, එබැවින් සංඛ්යාත්මක විග්රහකය 0.1 ආදානය ලබා දෙමින් දෙවැන්නාට වාසිදායක වනු ඇත.
(එම සංඛ්යා දෙක අතර වෙනස වන්නේ අප විසින් තීරණය කළ යුතු "කුඩාම පෙත්ත" වන අතර එය ඉහළ නැඹුරුවක් හඳුන්වා දෙන හෝ බැහැර කළ යුතු අතර එය පහත් නැඹුරුවක් හඳුන්වා දෙයි. එම කුඩාම පෙත්ත සඳහා තාක්ෂණික පදය ulp වේ.)
0.2 සම්බන්ධයෙන් ගත් කල, සංඛ්යා සියල්ලම එක හා සමාන වන අතර එය 2 ක සාධකයකින් පරිමාණය කර ඇත. නැවතත්, අපි 0.2 ට වඩා මඳක් වැඩි අගයට කැමැත්තෙමු.
මෙම අවස්ථා දෙකෙහිම, 0.1 සහ 0.2 සඳහා වන ආසන්න කිරීම්වල සුළු නැඹුරුවක් ඇති බව සලකන්න. අප මෙම පක්ෂග්රාහී දෑ ප්රමාණවත් ලෙස එකතු කළහොත්, ඒවා අපට අවශ්ය දෙයින් තව දුරටත් away ත් කරනු ඇති අතර ඇත්ත වශයෙන්ම 0.1 + 0.2 සම්බන්ධයෙන් ගත් කල, නැඹුරුව ප්රමාණවත් තරම් ඉහළ අගයක් ගන්නා අතර එහි ප්රති number ලයක් ලෙස ඇති සංඛ්යාව තවදුරටත් ආසන්නතම අංකය නොවේ සිට 0.3 දක්වා.
විශේෂයෙන් ම, 0.1 + 0.2 ඇත්තටම 0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 = 0.3000000000000000444089209850062616169452667236328125, 0.3 ආසන්නතම සංඛ්යාව ඇත්තටම 0,299999999999999988897769753748434595763683319091796875 තිබෙන්නකි.
PS සමහර ක්රමලේඛන භාෂාවන් පෙති හරියටම දහයෙන් බෙදිය හැකි පීසා කටර් ද සපයයි . එවැනි පීසා කටර් අසාමාන්ය වුවත්, ඔබට එකකට ප්රවේශය තිබේ නම්, පෙත්තකින් හරියටම දහයෙන් එකක් හෝ පහෙන් එකක් ලබා ගැනීමට හැකි වීම වැදගත් වන විට ඔබ එය භාවිතා කළ යුතුය.
පාවෙන ලක්ෂ්ය වටකුරු දෝෂ. 5 හි මූලික සාධකය නැතිවීම නිසා 0.1 පාදම -10 හි හරියටම නිවැරදිව නිරූපණය කළ නොහැක. 1/3 දශමයෙන් නිරූපණය කිරීම සඳහා අසීමිත සංඛ්යා සංඛ්යාවක් ගන්නා සේම, පාදම -3 හි "0.1" වේ. 0.1 පාදම -2 හි අසීමිත සංඛ්යා සංඛ්යාවක් ගනී, එහිදී එය පාදම -10 හි නොමැත. පරිගණකවල අසීමිත මතක ප්රමාණයක් නොමැත.
අනෙක් නිවැරදි පිළිතුරු වලට අමතරව, පාවෙන ලක්ෂ්ය අංක ගණිතයේ ගැටළු වළක්වා ගැනීම සඳහා ඔබේ අගයන් පරිමාණය කිරීම සලකා බැලීමට ඔබට අවශ්ය විය හැකිය.
උදාහරණයක් වශයෙන්:
var result = 1.0 + 2.0; // result === 3.0 returns true
... වෙනුවට:
var result = 0.1 + 0.2; // result === 0.3 returns false
ප්රකාශනය ජාවාස්ක්රිප්ට් වලින් 0.1 + 0.2 === 0.3
නැවත පැමිණේ false
, නමුත් වාසනාවකට පාවෙන ලක්ෂ්යයේ පූර්ණ සංඛ්යා අංක ගණිතය හරියටම වේ, එබැවින් පරිමාණයෙන් දශම නිරූපණ දෝෂ වළක්වා ගත හැකිය.
ප්රායෝගික උදාහරණයක් ලෙස, නිවැරදි පරම කොහෙද ඉපිලුම් ලක්ෂ්ය ගැටළු මඟහරවා ගැනීම සඳහා, එය නිර්දේශ කරනු ලැබේ 1 ශත සංඛ්යාව නියෝජනය ලෙස සම්පූර්ණ සංඛ්යාවක් මුදල් හැසිරවීමට: 2550
ශත වෙනුවට 25.50
ඩොලර්.
1 ඩග්ලස් ක්රොක්ෆර්ඩ්: ජාවාස්ක්රිප්ට්: හොඳ කොටස් : උපග්රන්ථය ඒ - භයානක කොටස් (පිටුව 105) .
මගේ පිළිතුර තරමක් දිගු බැවින් මම එය කොටස් තුනකට බෙදා ඇත්තෙමි. ප්රශ්නය පාවෙන ලක්ෂ්ය ගණිතය පිළිබඳ බැවින්, යන්ත්රය ඇත්ත වශයෙන්ම කරන්නේ කුමක්ද යන්න පිළිබඳව මම අවධාරණය කර ඇත්තෙමි. මම එය ද්විත්ව (බිට් 64) නිරවද්යතාවයට විශේෂිත කර ඇත, නමුත් තර්කය ඕනෑම පාවෙන ලක්ෂ්ය ගණිතයකට සමානව අදාළ වේ.
පෙරවදන
ක IEEE 754 ද්විත්ව නිරවද්යතාවයකින් ද්විමය ඉපිලුම් ලක්ෂ්ය ආකෘතිය (binary64) අංකය ආකෘති ගණනාවක් නියෝජනය
අගය = (-1) ^ s * (1.m 51 m 50 ... m 2 m 1 m 0 ) 2 * 2 e-1023
බිටු 64 කින්:
1
අංකය negative ණ නම්, 0
එසේ නොමැති නම් 1 .1.
සෑම විටම 2 මඟ හැරී ඇත 1
.1 - IEEE 754 වන සංකල්පය සඳහා ඉඩ අත්සන් ශුන්ය - +0
හා -0
වෙනස් ප්රතිකාර ඇත: 1 / (+0)
ධනාත්මක අනන්තය ය; 1 / (-0)
negative ණ අනන්තය. ශුන්ය අගයන් සඳහා, මැන්ටිස්සා සහ on ාතීය බිටු සියල්ලම ශුන්ය වේ. සටහන: ශුන්ය අගයන් (+0 සහ -0) පැහැදිලිවම 2 ලෙස වර්ගීකරණය කර නොමැත .
2 - ශුන්යයේ ඕෆ්සෙට් on ාතයක් (සහ ගම්ය වන 0.
) ඇති සංඛ්යාත්මක සංඛ්යා සඳහා මෙය නොවේ . නිත්ය ද්විත්ව නිරවද්යතා සංඛ්යා පරාසය d min ≤ | x | Min d max , මෙහි d min (කුඩාම නිරූපණය කළ හැකි නොවන අංකය) 2 -1023 - 51 (≈ 4.94 * 10 -324 ) සහ d max (විශාලතම නිත්ය අංකය, මැන්ටිස්සා මුළුමනින්ම 1
s වලින් සමන්විත වේ ) 2 -1023 + 1 - 2 -1023 - 51 (≈ 2.225 * 10 -308 ).
ද්විත්ව නිරවද්යතා සංඛ්යාවක් ද්විමය බවට හැරවීම
ද්විත්ව නිරවද්යතාවයකින් යුත් පාවෙන ලක්ෂ්ය සංඛ්යාවක් ද්විමය බවට පරිවර්තනය කිරීම සඳහා බොහෝ මාර්ගගත පරිවර්තකයන් පවතී (උදා: binaryconvert.com හි ), නමුත් මෙහි ද්විත්ව නිරවද්යතා අංකයක් සඳහා IEEE 754 නිරූපණය ලබා ගැනීම සඳහා සාම්පල C # කේතයක් ඇත (මම කොටස් තුන කොලෝන් සමඟ වෙන් කරමි ( :
) :
public static string BinaryRepresentation(double value)
{
long valueInLongType = BitConverter.DoubleToInt64Bits(value);
string bits = Convert.ToString(valueInLongType, 2);
string leadingZeros = new string('0', 64 - bits.Length);
string binaryRepresentation = leadingZeros + bits;
string sign = binaryRepresentation[0].ToString();
string exponent = binaryRepresentation.Substring(1, 11);
string mantissa = binaryRepresentation.Substring(12);
return string.Format("{0}:{1}:{2}", sign, exponent, mantissa);
}
කාරණය වෙත ළඟා වීම: මුල් ප්රශ්නය
(TL; DR අනුවාදය සඳහා පහළට යන්න)
කැටෝ ජොන්ස්ටන් (ප්රශ්න අසන්නා) ඇසුවේ ඇයි 0.1 + 0.2! = 0.3.
ද්විමය වශයෙන් ලියා ඇත (කොලෝන් කොටස් තුන වෙන් කරයි), IEEE 754 අගයන් නිරූපණය කරන්නේ:
0.1 => 0:01111111011:1001100110011001100110011001100110011001100110011010
0.2 => 0:01111111100:1001100110011001100110011001100110011001100110011010
මැන්ටිස්සා පුනරාවර්තන ඉලක්කම් වලින් සමන්විත බව සලකන්න 0011
. මේ ප්රධාන ගණනය කිරීම් කිසිදු දෝෂයක් වන්නේ ඇයි කිරීමට - 0.1, 0.2 හා 0.3 ද්විමය නියෝජනය කළ නොහැකි හරියටම දී පරිමිත ද්විමය බිට් ගණන වැඩි ඕනෑම 1/9 ට වඩා, 1/3 හෝ 1/7 තුල හරියටම නියෝජනය කළ හැකි දශම සංඛ්යා .
අපට on ාතයේ බලය 52 කින් අඩු කළ හැකි අතර ද්විමය නිරූපණයේ ලක්ෂ්යය ස්ථාන 52 කින් දකුණට මාරු කළ හැකිය (10 -3 * 1.23 == 10 -5 * 123 වැනි). එවිට ද්විමය නිරූපණය * 2 p ස්වරූපයෙන් නිරූපණය වන නිශ්චිත අගය ලෙස නිරූපණය කිරීමට මෙය අපට හැකියාව ලබා දෙයි . මෙහි 'a' යනු පූර්ණ සංඛ්යාවක් වේ.
On ාතයන් දශමයට පරිවර්තනය කිරීම, ඕෆ්සෙට් ඉවත් කිරීම සහ ඇඟවුම් කළ 1
(වර්ග වරහන් වල) නැවත එකතු කිරීම , 0.1 සහ 0.2:
0.1 => 2^-4 * [1].1001100110011001100110011001100110011001100110011010
0.2 => 2^-3 * [1].1001100110011001100110011001100110011001100110011010
or
0.1 => 2^-56 * 7205759403792794 = 0.1000000000000000055511151231257827021181583404541015625
0.2 => 2^-55 * 7205759403792794 = 0.200000000000000011102230246251565404236316680908203125
අංක දෙකක් එකතු කිරීම සඳහා, on ාතකය සමාන විය යුතුය, එනම්:
0.1 => 2^-3 * 0.1100110011001100110011001100110011001100110011001101(0)
0.2 => 2^-3 * 1.1001100110011001100110011001100110011001100110011010
sum = 2^-3 * 10.0110011001100110011001100110011001100110011001100111
or
0.1 => 2^-55 * 3602879701896397 = 0.1000000000000000055511151231257827021181583404541015625
0.2 => 2^-55 * 7205759403792794 = 0.200000000000000011102230246251565404236316680908203125
sum = 2^-55 * 10808639105689191 = 0.3000000000000000166533453693773481063544750213623046875
එකතුව 2 n * 1 ආකාරයෙන් නොවන බැවින් {bbb} අපි on ාතකය එකකින් වැඩි කර දශම ( ද්විමය ) ලක්ෂ්යය ලබා ගැනීමට මාරු කරමු :
sum = 2^-2 * 1.0011001100110011001100110011001100110011001100110011(1)
= 2^-54 * 5404319552844595.5 = 0.3000000000000000166533453693773481063544750213623046875
දැන් මැන්ටිස්සා හි බිටු 53 ක් ඇත (53 වන කොටස ඉහත පේළියේ වර්ග වරහන් වල ඇත). පෙරනිමි මාදිලිය යයි වරදවා වටහා IEEE 754 සඳහා 'යනු ළඟම වටය ' - එනම්, අංකය x අගයන් දෙක අතර වැටෙන වූ සහ ආ , අවම වශයෙන් සැලකිය යුතු ටිකක් ශූන්ය වටිනාකම තෝරා ගනු ලැබේ.
a = 2^-54 * 5404319552844595 = 0.299999999999999988897769753748434595763683319091796875
= 2^-2 * 1.0011001100110011001100110011001100110011001100110011
x = 2^-2 * 1.0011001100110011001100110011001100110011001100110011(1)
b = 2^-2 * 1.0011001100110011001100110011001100110011001100110100
= 2^-54 * 5404319552844596 = 0.3000000000000000444089209850062616169452667236328125
A සහ b වෙනස් වන්නේ අවසාන බිට් එකෙන් පමණක් බව සලකන්න ; ...0011
+ 1
= ...0100
. මෙම අවස්ථාවෙහිදී, අවම වශයෙන් සැලකිය යුතු බිංදුවක් සහිත අගය b වේ , එබැවින් එකතුව:
sum = 2^-2 * 1.0011001100110011001100110011001100110011001100110100
= 2^-54 * 5404319552844596 = 0.3000000000000000444089209850062616169452667236328125
0.3 හි ද්විමය නිරූපණය:
0.3 => 2^-2 * 1.0011001100110011001100110011001100110011001100110011
= 2^-54 * 5404319552844595 = 0.299999999999999988897769753748434595763683319091796875
එය වෙනස් වන්නේ 0.1 සහ 0.2 එකතුව 2 -54 හි ද්විමය නිරූපණයට පමණි .
0.1 සහ 0.2 යන ද්විමය නිරූපණය IEEE 754 මගින් අවසර දී ඇති සංඛ්යා වල වඩාත් නිවැරදි නිරූපණයන් වේ. පෙරනිමි වටකුරු මාදිලිය හේතුවෙන් මෙම නිරූපණයන් එකතු කිරීම මඟින් ප්රති results ල ලැබෙන්නේ අවම-වැදගත්-බිට් වලින් පමණක් වෙනස් වන අගයෙනි.
ටීඑල්; ඩී.ආර්
0.1 + 0.2
අයිඊඊඊ 754 ද්විමය නිරූපණයකින් ලිවීම (කොලෝන් කොටස් තුන වෙන් කරයි) සහ එය සංසන්දනය කිරීමේදී 0.3
, මෙය (මම විශේෂිත බිටු වර්ග වරහන් වල දමා ඇත):
0.1 + 0.2 => 0:01111111101:0011001100110011001100110011001100110011001100110[100]
0.3 => 0:01111111101:0011001100110011001100110011001100110011001100110[011]
නැවත දශමයට හරවන විට, මෙම අගයන්:
0.1 + 0.2 => 0.300000000000000044408920985006...
0.3 => 0.299999999999999988897769753748...
වෙනස හරියටම 2 -54 වන අතර එය ~ 5.5511151231258 × 10 -17 - මුල් අගයන් හා සසඳන විට වැදගත් නොවේ (බොහෝ යෙදුම් සඳහා).
පාවෙන ලක්ෂ්ය අංකයක අවසාන බිටු සංසන්දනය කිරීම සහජයෙන්ම භයානක ය, මන්දයත් “ සෑම පරිගණක විද්යා ist යෙක්ම පාවෙන ලක්ෂ්ය අංක ගණිතය ගැන දැනගත යුතු දේ ” (මෙම පිළිතුරේ සියලුම ප්රධාන කොටස් ආවරණය කරන) කියවන ඕනෑම කෙනෙකුට දැනගත හැකි වනු ඇත.
බොහෝ කැල්කියුලේටරයන් මෙම ගැටළුව මඟහරවා ගැනීම සඳහා අතිරේක ආරක්ෂක ඉලක්කම් භාවිතා කරයි , එය 0.1 + 0.2
ලබා දෙන්නේ කෙසේද 0.3
: අවසාන බිටු කිහිපය වටකුරු ය.
පරිගණකයේ ගබඩා කර ඇති පාවෙන ලක්ෂ්ය සංඛ්යා කොටස් දෙකකින් සමන්විත වේ, පූර්ණ සංඛ්යාවක් සහ on ාතයක් වන අතර එය පාදම පූර්ණ සංඛ්යා කොටසට ගෙන ගුණනය කරයි.
පරිගණක 10 පාදයේ වැඩ කරන්නේ නම්, 0.1
වනු ඇත 1 x 10⁻¹
, 0.2
වනු ඇත 2 x 10⁻¹
, සහ 0.3
වනු ඇත 3 x 10⁻¹
. පූර්ණ සංඛ්යා ගණිතය පහසු සහ නිරවද්ය බැවින් එකතු 0.1 + 0.2
කිරීමෙන් පැහැදිලිවම ප්රති result ල ලැබෙනු ඇත 0.3
.
පරිගණක සාමාන්යයෙන් 10 වන පාදයේ ක්රියා නොකරයි, ඒවා පදනම් 2 හි වැඩ කරයි. සමහර අගයන් සඳහා ඔබට තවමත් නිශ්චිත ප්රති results ල ලබා ගත හැකිය, නිදසුනක් 0.5
ලෙස 1 x 2⁻¹
සහ 0.25
තිබේ 1 x 2⁻²
, සහ ඒවා එකතු කිරීමෙන් ප්රති results ල 3 x 2⁻²
හෝ 0.75
. හරියටම.
ගැටළුව පැමිණෙන්නේ හරියටම 10 වන පාදයේ නොව 2 වන පාදයේ නොව නිරූපණය කළ හැකි සංඛ්යා සමඟ ය. එම සංඛ්යා ඒවායේ ආසන්නතම සමානතාවයට වට කළ යුතුය. ඉතා පොදු IEEE 64-bit ඉපිලුම් ලක්ෂ්ය ආකෘතිය උපකල්පනය, සමීප අංකය 0.1
කියන්නේ 3602879701896397 x 2⁻⁵⁵
, සහ සමීපතම අංකය 0.2
ඇත 7205759403792794 x 2⁻⁵⁵
; ඒවා එකට එකතු කිරීමෙන් 10808639105689191 x 2⁻⁵⁵
ප්රති results ල හෝ නිශ්චිත දශම අගයක් 0.3000000000000000444089209850062616169452667236328125
ලැබේ. පාවෙන ලක්ෂ්ය සංඛ්යා සාමාන්යයෙන් ප්රදර්ශනය සඳහා වටකුරු ය.
පාවෙන ලක්ෂ්ය වටකුරු දෝෂයකි. සිට කුමක්ද සෑම පරිගණක විද්යාඥ යුතුද දැන හඳුනා ඉපිලුම් ලක්ෂ්ය සමාන්තර ගැන :
අසීමිත බොහෝ තාත්වික සංඛ්යා සීමිත බිටු ගණනකට මිරිකීම සඳහා ආසන්න නිරූපණයක් අවශ්ය වේ. අසීමිත සංඛ්යා සංඛ්යාවක් තිබුණද, බොහෝ වැඩසටහන් වලදී පූර්ණ සංඛ්යා ගණනය කිරීමේ ප්රති result ලය බිටු 32 කින් ගබඩා කළ හැකිය. ඊට වෙනස්ව, ඕනෑම ස්ථාවර බිටු සංඛ්යාවක් ලබා දී ඇති විට, තාත්වික සංඛ්යා සමඟ බොහෝ ගණනය කිරීම් මඟින් බොහෝ බිටු භාවිතා කර හරියටම නිරූපණය කළ නොහැකි ප්රමාණ නිපදවනු ඇත. එබැවින් පාවෙන ලක්ෂ්ය ගණනය කිරීමේ ප්රති result ලය බොහෝ විට එහි සීමිත නිරූපණයට ගැලපෙන පරිදි වටකුරු කළ යුතුය. මෙම වටකුරු දෝෂය පාවෙන ලක්ෂ්ය ගණනය කිරීමේ ලක්ෂණයකි.
හොඳ පිළිතුරු ගොඩක් පළ කර ඇත, නමුත් මම තවත් එකක් එකතු කිරීමට කැමැත්තෙමි.
සියලුම සංඛ්යා පාවෙන / යුගල හරහා නිරූපණය කළ නොහැක. නිදසුනක් ලෙස, IEEE754 පාවෙන ලක්ෂ්ය ප්රමිතියේ තනි නිරවද්යතාවයකින් “0.2” අංකය “0.200000003” ලෙස නිරූපණය කෙරේ.
තොප්පිය යටතේ තාත්වික සංඛ්යා ගබඩා කිරීමේ ආකෘතිය පාවෙන අංක ලෙස නිරූපණය කරයි
ඔබ ටයිප් කළ හැක වුවද 0.2
පහසුවෙන්, FLT_RADIX
සහ DBL_RADIX
2 ය; "ද්විමය පාවෙන ලක්ෂ්ය අංක ගණිතය සඳහා IEEE ප්රමිතිය (ISO / IEEE STD 754-1985) භාවිතා කරන FPU සහිත පරිගණකයක් සඳහා 10 නොවේ."
එබැවින් එවැනි සංඛ්යා හරියටම නිරූපණය කිරීම ටිකක් අපහසුය. ඔබ අතරමැදි ගණනය කිරීමකින් තොරව මෙම විචල්යය පැහැදිලිව සඳහන් කළත්.
මෙම සුප්රසිද්ධ ද්විත්ව නිරවද්යතා ප්රශ්නයට අදාළ සමහර සංඛ්යාලේඛන.
0.1 (0.1 සිට 100 දක්වා) පියවරක් භාවිතා කරමින් සියලු අගයන් ( a + b ) එකතු කරන විට අපට නිරවද්ය දෝෂයක් සඳහා ~ 15% ක අවස්ථාවක් ඇත . දෝෂය තරමක් විශාල හෝ කුඩා අගයන් ඇති කළ හැකි බව සලකන්න. මෙන්න උදාහරණ කිහිපයක්:
0.1 + 0.2 = 0.30000000000000004 (BIGGER)
0.1 + 0.7 = 0.7999999999999999 (SMALLER)
...
1.7 + 1.9 = 3.5999999999999996 (SMALLER)
1.7 + 2.2 = 3.9000000000000004 (BIGGER)
...
3.2 + 3.6 = 6.800000000000001 (BIGGER)
3.2 + 4.4 = 7.6000000000000005 (BIGGER)
0.1 (100 සිට 0.1 දක්වා) පියවරක් භාවිතා කරමින් සියලු අගයන් ( a - b එහිදී a> b ) අඩු කරන විට අපට නිරවද්ය දෝෂයක් සඳහා ~ 34% ක අවස්ථාවක් ඇත . මෙන්න උදාහරණ කිහිපයක්:
0.6 - 0.2 = 0.39999999999999997 (SMALLER)
0.5 - 0.4 = 0.09999999999999998 (SMALLER)
...
2.1 - 0.2 = 1.9000000000000001 (BIGGER)
2.0 - 1.9 = 0.10000000000000009 (BIGGER)
...
100 - 99.9 = 0.09999999999999432 (SMALLER)
100 - 99.8 = 0.20000000000000284 (BIGGER)
* 15% සහ 34% සැබවින්ම විශාල ය, එබැවින් නිරවද්යතාව විශාල වැදගත්කමක් ඇති විට සෑම විටම බිග් ඩෙසිමල් භාවිතා කරන්න. දශම සංඛ්යා 2 ක් (පියවර 0.01) සමඟ තත්වය තව තවත් නරක අතට හැරේ (18% සහ 36%).
සාරාංශය
ස්ථානය අංක ගණිතමය පාවෙන වේ හරියටම, අවාසනාවකට මෙන්, එය මනා ලෙස අපේ සුපුරුදු පදනම-10 සංඛ්යා නිරූපණය සමග, එය දුටුවේ ඒ නිසා අපි බොහෝ විට එය තරමක් අප ලියූ දේ වලින් ඉවත් වන බව ආදාන දෙනවා නොගැලපේ.
0.01, 0.02, 0.03, 0.04 ... 0.24 වැනි සරල සංඛ්යා පවා ද්විමය භාග ලෙස හරියටම නිරූපණය නොවේ. ඔබ 0.01, .02, .03 ... ලෙස ගණන් කළහොත්, ඔබ 0.25 දක්වා ළඟා වන තෙක් නොව, 2 වන පාදයේ නිරූපණය කළ හැකි පළමු භාගය ඔබට ලැබෙනු ඇත . ඔබ එෆ්.පී. භාවිතා කිරීමට උත්සාහ කළේ නම්, ඔබේ 0.01 තරමක් අක්රීය වනු ඇත, එබැවින් ඔවුන්ගෙන් 25 ක් ඉතා නිවැරදිව 0.25 දක්වා එකතු කිරීමට ඇති එකම ක්රමය වන්නේ ආරක්ෂක බිටු සහ වටකුරු සම්බන්ධ දිගු හේතු දාමයක් අවශ්ය වීමයි. අනාවැකි කීම දුෂ්කර බැවින් අපි දෑත් ඔසවා "එෆ්පී නිරවද්ය" යැයි කියමු , නමුත් එය ඇත්ත වශයෙන්ම සත්ය නොවේ.
අපි නිරන්තරයෙන් එෆ්පී දෘඩාංග ලබා දෙන්නේ 10 වන පාදයේ සරල යැයි පෙනෙන නමුත් 2 වන පාදයේ පුනරාවර්තන භාගයකි.
මෙය සිදුවූයේ කෙසේ?
අප දශමයෙන් ලියන විට, සෑම භාගයක්ම (විශේෂයෙන්, අවසන් වන සෑම දශමයක්ම) ආකෘතියේ තාර්කික සංඛ්යාවක් වේ
a / (2 n x 5 m )
ද්විමය වශයෙන්, අපට ලැබෙන්නේ 2 n පදය පමණි, එනම්:
a / 2 n
ඒ නිසා දශම, අපි නියෝජනය නොහැකි 1 / 3 . පදනම 10 ප්රථමක සාධකය ලෙස, අපි ද්විමය භාග සංඛ්යාවක් ලෙස ලිවිය හැකිය සෑම අංක 2 ඇතුළත් වන බැවින් ද පදනම 10 භාග සංඛ්යාවක් ලෙස ලිවිය හැක. කෙසේ වෙතත්, අපි මූලික 10 භාගයක් ලෙස ලියන කිසිවක් ද්විමය වශයෙන් නිරූපණය කළ නොහැක. 0.01, 0.02, 0.03 ... 0.99 පරාසය තුළ අපගේ FP ආකෘතියෙන් දැක්විය හැක්කේ අංක තුනක් පමණි : 0.25, 0.50, සහ 0.75, මන්ද ඒවා 1/4, 1/2 සහ 3/4 වන බැවින්, සියලු සංඛ්යා 2 n පදය පමණක් භාවිතා කරන ප්රධාන සාධකය සමඟ .
පදනම 10 අප නියෝජනය කළ නොහැකි 1 / 3 . නමුත් ද්විමය, අපි කරන්න බැහැ 1 / 10 හෝ 1 / 3 .
එබැවින් සෑම ද්විමය භාගයක්ම දශමයෙන් ලිවිය හැකි නමුත් ප්රතිලෝම සත්ය නොවේ. ඇත්ත වශයෙන්ම බොහෝ දශම භාගයන් ද්විමය වශයෙන් පුනරාවර්තනය වේ.
එය සමඟ කටයුතු කිරීම
සංවර්ධකයින්ට සාමාන්යයෙන් උපදෙස් දෙනුයේ <එප්සිලන් සැසඳීම් කිරීමට, වඩා හොඳ උපදෙස් විය හැක්කේ සමෝධානික අගයන් (සී පුස්තකාලයේ: වටය () සහ රවුන්ඩ් (), එනම් එෆ්පී ආකෘතියේ රැඳී සිටීම) හා පසුව සංසන්දනය කිරීමයි. නිශ්චිත දශම භාග භාගයකට රවුම් කිරීම ප්රතිදානයේ බොහෝ ගැටලු විසඳයි.
එසේම, තාත්වික සංඛ්යා බිඳීමේ ගැටළු මත (මුල්, භයානක මිල අධික පරිගණක සඳහා එෆ්.පී. සොයා ගන්නා ලද ගැටළු) විශ්වයේ භෞතික නියතයන් සහ අනෙකුත් සියලුම මිනුම් දන්නේ සැලකිය යුතු සංඛ්යා සංඛ්යාවක් පමණක් වන බැවින් සමස්ත ගැටළු අවකාශය කෙසේ වෙතත් "නිරවද්ය" විය. FP “නිරවද්යතාවය” මේ ආකාරයේ යෙදුමක ගැටළුවක් නොවේ.
බෝංචි ගණනය කිරීම සඳහා මිනිසුන් එෆ්.පී. භාවිතා කිරීමට උත්සාහ කරන විට සමස්ත ප්රශ්නයම ඇත්ත වශයෙන්ම පැන නගී. එය ඒ සඳහා ක්රියා කරයි, නමුත් ඔබ ඒකාග්ර අගයන්ට ඇලී සිටියහොත් පමණක්, එය භාවිතා කිරීමේ ලක්ෂ්යය පරාජය කරන්නේ කුමන ආකාරයේද? මේ නිසා අපට එම දශම භාගයේ මෘදුකාංග පුස්තකාල තිබේ.
මම ක්රිස්ගේ පීසා පිළිතුරට කැමතියි , මන්ද එය “නිරවද්යතාවය” පිළිබඳ සුපුරුදු අත් සේදීම පමණක් නොව සැබෑ ගැටළුව විස්තර කරයි. එෆ්පී හුදෙක් "සාවද්ය" නම්, අපට එය නිවැරදි කළ හැකි අතර එය දශක ගණනාවකට පෙර සිදු කරනු ඇත. අප සතුව නැති හේතුව නම්, එෆ්පී ආකෘතිය සංයුක්ත හා වේගවත් වන අතර එය සංඛ්යා විශාල ප්රමාණයක් පොඩි කිරීමට හොඳම ක්රමයයි. එසේම, එය අභ්යවකාශ යුගයේ සහ ආයුධ ධාවන තරඟයේ උරුමයක් වන අතර කුඩා මතක පද්ධති භාවිතා කරමින් ඉතා මන්දගාමී පරිගණක සමඟ විශාල ගැටලු විසඳීමට මුල් උත්සාහයන් දරයි. (සමහර විට, බිට් 1 ගබඩා කිරීම සඳහා තනි චුම්බක හරයන් , නමුත් එය තවත් කතාවකි. )
නිගමනය
ඔබ බැංකුවක බෝංචි ගණන් කරන්නේ නම්, දශම නූල් නිරූපණයන් භාවිතා කරන මෘදුකාංග විසඳුම් හොඳින් ක්රියාත්මක වේ. නමුත් ඔබට ක්වොන්ටම් වර්ණදේහ හෝ වායුගති විද්යාව ඒ ආකාරයෙන් කළ නොහැක.
nextafter()
. එසේම, ඔබට පාවෙන සංඛ්යා පූර්ණ සංඛ්යාවක් ලෙස සංසන්දනය කර ඒවා දෙකම negative ණාත්මක වන විට හැර නිවැරදි පිළිතුර ලබා ගත හැකිය (සං sign ා-විශාලත්වය එදිරිව 2 හි අනුපූරකය නිසා).
ඉදිරිපත් කිරීම සඳහා හොඳම විසඳුම මම පහත ක්රමවේදය සොයා ගත් බව පැවසිය හැකිය:
parseFloat((0.1 + 0.2).toFixed(10)) => Will return 0.3
එය හොඳම විසඳුම වන්නේ මන්දැයි මට පැහැදිලි කරන්නම්. ඉහත පිළිතුරු වල සඳහන් කර ඇති අනෙක් අය, ගැටළුව විසඳීම සඳහා ජාවාස්ක්රිප්ට් ටුෆික්ස්ඩ් () ශ්රිතය භාවිතා කිරීමට සූදානම්ව සිටීම හොඳ අදහසකි. නමුත් බොහෝ දුරට ඔබ යම් යම් ගැටළු වලට මුහුණ දෙනු ඇත.
ඔබ වැනි පාවෙන සංඛ්යා දෙකක් එකතු කරන්න යන්නේ සිතන්න 0.2
හා 0.7
: මෙහි එය 0.2 + 0.7 = 0.8999999999999999
.
ඔබ අපේක්ෂිත ප්රති result 0.9
ලය වූයේ මෙම නඩුවේ ඉලක්කම් 1 ක නිරවද්යතාවයකින් ඔබට ප්රති result ලයක් අවශ්ය බවයි. එබැවින් ඔබ භාවිතා කළ යුතුව තිබූ (0.2 + 0.7).tofixed(1)
නමුත් ඔබට නිශ්චිත පරාමිතියක් toFixed () වෙත ලබා දිය නොහැක, මන්ද එය ලබා දී ඇති අංකය මත රඳා පවතී.
`0.22 + 0.7 = 0.9199999999999999`
මෙම උදාහරණයේ දී ඔබට ඉලක්කම් 2 ක නිරවද්යතාවයක් අවශ්ය වන අතර එය එසේ විය යුතුය toFixed(2)
, එබැවින් ලබා දී ඇති සෑම පාවෙන අංකයකට ගැලපෙන පරාමිතිය කුමක් විය යුතුද?
එවිට සෑම තත්වයකදීම එය 10 ක් විය හැකි යැයි ඔබට පැවසිය හැකිය:
(0.2 + 0.7).toFixed(10) => Result will be "0.9000000000"
අපොයි! 9 න් පසු එම අනවශ්ය ශුන්යයන් සමඟ ඔබ කුමක් කරන්නද? ඔබ කැමති පරිදි එය සෑදීම සඳහා එය පාවෙන බවට පරිවර්තනය කිරීමට කාලයයි:
parseFloat((0.2 + 0.7).toFixed(10)) => Result will be 0.9
දැන් ඔබ විසඳුම සොයා ගත් පසු, එය මෙවැනි ශ්රිතයක් ලෙස ඉදිරිපත් කිරීම වඩා හොඳය:
function floatify(number){
return parseFloat((number).toFixed(10));
}
අපි එය ඔබම උත්සාහ කරමු:
function floatify(number){
return parseFloat((number).toFixed(10));
}
function addUp(){
var number1 = +$("#number1").val();
var number2 = +$("#number2").val();
var unexpectedResult = number1 + number2;
var expectedResult = floatify(number1 + number2);
$("#unexpectedResult").text(unexpectedResult);
$("#expectedResult").text(expectedResult);
}
addUp();
input{
width: 50px;
}
#expectedResult{
color: green;
}
#unexpectedResult{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="number1" value="0.2" onclick="addUp()" onkeyup="addUp()"/> +
<input id="number2" value="0.7" onclick="addUp()" onkeyup="addUp()"/> =
<p>Expected Result: <span id="expectedResult"></span></p>
<p>Unexpected Result: <span id="unexpectedResult"></span></p>
ඔබට එය මේ ආකාරයෙන් භාවිතා කළ හැකිය:
var x = 0.2 + 0.7;
floatify(x); => Result: 0.9
ලෙස W3SCHOOLS ද තවත් විසඳුමක් නොමැති බවයි, ඔබ ඉහත ප්රශ්නය විසඳීම සඳහා බොහෝ සෙයින් වැඩි විය හැකි අතර, බෙදා:
var x = (0.2 * 10 + 0.1 * 10) / 10; // x will be 0.3
(0.2 + 0.1) * 10 / 10
එය එක හා සමාන යැයි පෙනුනද එය කිසිසේත් ක්රියාත්මක නොවන බව මතක තබා ගන්න ! ආදාන පාවීම නිවැරදි ප්රතිදාන පාවෙන බවට පරිවර්තනය කරන ශ්රිතයක් ලෙස මට එය යෙදිය හැකි බැවින් මම පළමු විසඳුමට කැමැත්තෙමි.
ඔබ ඩක් ටේප් විසඳුම උත්සාහ කළාද?
දෝෂ ඇති වූ විට තීරණය කිරීමට උත්සාහ කර ඒවා කෙටියෙන් නම් ඒවා නිවැරදි කරන්න, එය ලස්සන නැත නමුත් සමහර ගැටළු සඳහා එය එකම විසඳුම වන අතර මෙය ඒවායින් එකකි.
if( (n * 0.1) < 100.0 ) { return n * 0.1 - 0.000000000000001 ;}
else { return n * 0.1 + 0.000000000000001 ;}
C # හි විද්යාත්මක සමාකරණ ව්යාපෘතියක දී මට ද එම ගැටලුවම ඇති අතර, ඔබ සමනල ආචරණය නොසලකා හැරියහොත් එය විශාල මේද මකරෙකු වෙත හැරී ඔබව **
ගණනය කිරීමේ අරමුණු සඳහා පරිගණක ද්විමය (පදනම් 2) සංඛ්යා පද්ධතියක් භාවිතා කරන අතර අප දශම (පදනම් 10) භාවිතා කරන නිසා එම අමුතු සංඛ්යා දිස් වේ.
ද්විමය හෝ දශම හෝ දෙකම නිශ්චිතවම නිරූපණය කළ නොහැකි භාගික සංඛ්යා බහුතරයක් ඇත. ප්රති ult ලය - වටකුරු (නමුත් නිවැරදි) සංඛ්යා ප්රති .ල.
මෙම ප්රශ්නයේ බොහෝ අනුපිටපත් නිශ්චිත සංඛ්යා මත පාවෙන ලක්ෂ්ය වටයේ බලපෑම ගැන විමසයි. ප්රායෝගිකව, පොලී ගණනය කිරීම්වල නිවැරදි ප්රති results ල දෙස බැලීමෙන් පමණක් නොව එය ක්රියාත්මක වන ආකාරය පිළිබඳ හැඟීමක් ලබා ගැනීම පහසුය. සමහර භාෂාවන් ඒ සඳහා ක්රම සපයයි - a float
හෝ ජාවා double
වෙත පරිවර්තනය කිරීම වැනි BigDecimal
.
මෙය භාෂා-අ nost ෙයවාදී ප්රශ්නයක් බැවින් එයට දශම සිට පාවෙන ලක්ෂ්ය පරිවර්තකය වැනි භාෂා-අ nost ෙයවාදී මෙවලම් අවශ්ය වේ.
ප්රශ්නයේ අංකවලට එය යෙදීම, ද්විත්ව ලෙස සලකනු ලැබේ:
0.1 0.1000000000000000055511151231257827021181583404541015625,
0.2 0.200000000000000011102230246251565404236316680908203125,
0.3 0.299999999999999988897769753748434595763683319091796875, සහ
0.30000000000000004 0.3000000000000000444089209850062616169452667236328125 බවට පරිවර්තනය වේ.
පළමු සංඛ්යා දෙක අතින් හෝ පූර්ණ නිරවද්ය කැල්කියුලේටරය වැනි දශම කැල්කියුලේටරයක එකතු කිරීමෙන් සත්ය යෙදවුම්වල නිශ්චිත එකතුව 0.3000000000000000166533453693773481063544750213623046875 වේ.
එය 0.3 ට සමාන වටකුරු නම් වටකුරු දෝෂය 0.0000000000000000277555756156289135105907917022705078125 වේ. 0.30000000000000004 ට සමාන වටය ද වටකුරු දෝෂයක් ලබා දෙයි 0.0000000000000000277555756156289135105907917022705078125. වටකුරු-පවා-ටයි පටිය අදාළ වේ.
පාවෙන ලක්ෂ්ය පරිවර්තකය වෙත ආපසු යන විට, 0.30000000000000004 සඳහා වන අමු ෂඩාස්රාකාරය 3fd3333333333334 වන අතර එය ඉරට්ටේ අංකයකින් අවසන් වන අතර එම නිසා නිවැරදි ප්රති .ලය වේ.
කිසිවෙකු මෙය සඳහන් කර නැති නිසා ...
පයිතන් සහ ජාවා වැනි සමහර ඉහළ මට්ටමේ භාෂා ද්විමය පාවෙන ලක්ෂ්ය සීමාවන් මඟහරවා ගැනීම සඳහා මෙවලම් සමඟ පැමිණේ. උදාහරණයක් වශයෙන්:
පයිතන්ගේ decimal
මොඩියුලය සහ ජාවා BigDecimal
පන්තිය , දශම අංකනය සමඟ අභ්යන්තරව සංඛ්යා නිරූපණය කරයි (ද්විමය අංකනයට ප්රතිවිරුද්ධව). දෙකම සීමිත නිරවද්යතාවයක් ඇත, එබැවින් ඒවා තවමත් දෝෂ සහිත වේ, කෙසේ වෙතත් ඒවා ද්විමය පාවෙන ලක්ෂ්ය අංක ගණිතයේ ඇති පොදු ගැටළු විසඳයි.
මුදල් සමඟ ගනුදෙනු කිරීමේදී දශම ඉතා හොඳයි: ශත දහයක් සහ ශත විස්සක් සෑම විටම හරියටම ශත තිහකි:
>>> 0.1 + 0.2 == 0.3
False
>>> Decimal('0.1') + Decimal('0.2') == Decimal('0.3')
True
පයිතන්ගේ decimal
මොඩියුලය IEEE ප්රමිතිය 854-1987 මත පදනම් වේ .
පයිතන්ගේ fractions
මොඩියුලය සහ අපාචි පොදු BigFraction
පන්තිය . දෙකම තාර්කික සංඛ්යා (numerator, denominator)
යුගල වශයෙන් නිරූපණය කරන අතර ඒවා දශම පාවෙන ලක්ෂ්ය අංක ගණිතයට වඩා නිවැරදි ප්රති results ල ලබා දිය හැකිය.
මෙම විසඳුම් දෙකම පරිපූර්ණ නොවේ (විශේෂයෙන් අපි කාර්ය සාධනය දෙස බැලුවහොත් හෝ අපට ඉතා ඉහළ නිරවද්යතාවයක් අවශ්ය නම්), නමුත් තවමත් ඒවා ද්විමය පාවෙන ලක්ෂ්ය අංක ගණිතයේ ගැටලු රාශියක් විසඳයි.
මට එකතු කළ හැකිද; මිනිසුන් සැමවිටම මෙය පරිගණක ගැටලුවක් යැයි උපකල්පනය කරයි, නමුත් ඔබ ඔබේ දෑතින් (10 වන පදනම) ගණන් (1/3+1/3=2/3)=true
කළහොත්, ඔබට 0.333 ... 0.333 ට එකතු කිරීමට අනන්තය නොමැති නම් ඔබට ලබා ගත නොහැක ... එබැවින් (1/10+2/10)!==3/10
පාදමේ ගැටලුව මෙන් ම 2, ඔබ එය 0.333 + 0.333 = 0.666 දක්වා කප්පාදු කර බොහෝ විට එය 0.667 දක්වා වට කර ඇති අතර එය තාක්ෂණිකව සාවද්ය වේ.
තෘතීය වශයෙන් ගණන් කරන්න, නමුත් තුනෙන් එකක් ගැටළුවක් නොවේ - සමහරවිට එක් අතකින් ඇඟිලි 15 ක් ඇති සමහර ජාතීන් ඔබේ දශම ගණිතය කැඩී ඇත්තේ මන්දැයි අසනු ඇත ...
ඩිජිටල් පරිගණකයක ක්රියාත්මක කළ හැකි ආකාරයේ පාවෙන ලක්ෂ්ය ගණිතය අනිවාර්යයෙන්ම ඒවා මත සත්ය සංඛ්යා හා මෙහෙයුම් පිළිබඳ දළ විශ්ලේෂණයක් භාවිතා කරයි. ( සම්මත අනුවාදය පිටු පනහකට අධික සංඛ්යාවක ලියකියවිලි දක්වා දිවෙන අතර එහි වැරදි සහ තවදුරටත් පිරිපහදු කිරීම සම්බන්ධයෙන් කටයුතු කිරීමට කමිටුවක් ඇත.)
මෙම ඇස්තමේන්තුව විවිධ වර්ගවල ඇස්තමේන්තු වල මිශ්රණයකි, ඒ සෑම එකක්ම නිරවද්යතාවයෙන් නිශ්චිත අපගමනය හේතුවෙන් නොසලකා හැරීමට හෝ ප්රවේශමෙන් ගණනය කළ හැකිය. දෘඩාංග හා මෘදුකාංග මට්ටම් දෙකෙහිම සුවිශේෂී අවස්ථා ගණනාවක් ද ඊට සම්බන්ධ වන අතර බොහෝ දෙනා නොදැනුවත්ව මවාපාමින් අතීතයේ ගමන් කරයි.
ඔබට අසීමිත නිරවද්යතාවයක් අවශ්ය නම් (using අංකය භාවිතා කිරීම, උදාහරණයක් ලෙස, එහි කෙටි ස්ථාවරය වෙනුවට), ඔබ සංකේතාත්මක ගණිත වැඩසටහනක් ලිවීම හෝ භාවිතා කිරීම කළ යුතුය.
නමුත් සමහර විට පාවෙන ලක්ෂ්ය ගණිතය වටිනාකමින් නොපැහැදිලි වන අතර තර්කනය සහ දෝෂ ඉක්මනින් සමුච්චය විය හැකි අතර, ඒ සඳහා ඔබේ අවශ්යතා සහ පරීක්ෂණ ලිවිය හැකිය, එවිට ඔබේ කේතය නිතරම ඇති දේ සමඟ ලබා ගත හැකිය. ඔබේ FPU.
විනෝදය සඳහා, මම සම්මත C99 හි නිර්වචන අනුගමනය කරමින්, පාවෙන නිරූපණය සමඟ සෙල්ලම් කළ අතර මම පහත කේතය ලිව්වෙමි.
කේතය වෙන් කරන ලද කණ්ඩායම් 3 ක පාවෙන ද්විමය නිරූපණය මුද්රණය කරයි
SIGN EXPONENT FRACTION
ඉන්පසු එය යම් මුදලක් මුද්රණය කරයි, එය ප්රමාණවත් නිරවද්යතාවයකින් සාරාංශ කළ විට, එය දෘඩාංගවල සැබවින්ම පවතින අගය පෙන්වයි.
ඒ නිසා ඔබ ලියන්න විට float x = 999...
, සම්පාදකවරයා උත්සවයට විසින් මුද්රණය ටිකක් නියෝජන දී එම සංඛ්යාව පරිවර්තනය කරනු ඇත xx
උත්සවයට විසින් මුද්රණය කර ඇති මුදල එවැනි yy
ලබා දී සංඛ්යාවට සමාන විය.
යථාර්ථයේ දී, මෙම එකතුව දළ වශයෙන් පමණකි. අංක 999,999,999 සඳහා සම්පාදකයා විසින් පාවෙන අංකය 1,000,000,000 ලෙස නිරූපණය කරනු ඇත
කේතයෙන් පසුව මම කොන්සෝල සැසියක් අමුණන්නෙමි, එහිදී මම දෘඩාංගවල සැබවින්ම පවතින නියතයන් (us ණ PI සහ 999999999) යන දෙකෙහිම පද එකතුව ගණනය කරමි.
#include <stdio.h>
#include <limits.h>
void
xx(float *x)
{
unsigned char i = sizeof(*x)*CHAR_BIT-1;
do {
switch (i) {
case 31:
printf("sign:");
break;
case 30:
printf("exponent:");
break;
case 23:
printf("fraction:");
break;
}
char b=(*(unsigned long long*)x&((unsigned long long)1<<i))!=0;
printf("%d ", b);
} while (i--);
printf("\n");
}
void
yy(float a)
{
int sign=!(*(unsigned long long*)&a&((unsigned long long)1<<31));
int fraction = ((1<<23)-1)&(*(int*)&a);
int exponent = (255&((*(int*)&a)>>23))-127;
printf(sign?"positive" " ( 1+":"negative" " ( 1+");
unsigned int i = 1<<22;
unsigned int j = 1;
do {
char b=(fraction&i)!=0;
b&&(printf("1/(%d) %c", 1<<j, (fraction&(i-1))?'+':')' ), 0);
} while (j++, i>>=1);
printf("*2^%d", exponent);
printf("\n");
}
void
main()
{
float x=-3.14;
float y=999999999;
printf("%lu\n", sizeof(x));
xx(&x);
xx(&y);
yy(x);
yy(y);
}
දෘඩාංගවල පවතින පාවෙන තථ්ය වටිනාකම ගණනය කරන කොන්සෝල සැසිය මෙන්න. මම bc
ප්රධාන වැඩසටහන මඟින් ප්රතිදානය කරන ලද පදවල එකතුව මුද්රණය කිරීමට භාවිතා කළෙමි . කෙනෙකුට එම මුදල පයිතන් repl
හෝ ඊට සමාන යමක් ඇතුළත් කළ හැකිය .
-- .../terra1/stub
@ qemacs f.c
-- .../terra1/stub
@ gcc f.c
-- .../terra1/stub
@ ./a.out
sign:1 exponent:1 0 0 0 0 0 0 fraction:0 1 0 0 1 0 0 0 1 1 1 1 0 1 0 1 1 1 0 0 0 0 1 1
sign:0 exponent:1 0 0 1 1 1 0 fraction:0 1 1 0 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 0 1 0 0 0
negative ( 1+1/(2) +1/(16) +1/(256) +1/(512) +1/(1024) +1/(2048) +1/(8192) +1/(32768) +1/(65536) +1/(131072) +1/(4194304) +1/(8388608) )*2^1
positive ( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
-- .../terra1/stub
@ bc
scale=15
( 1+1/(2) +1/(4) +1/(16) +1/(32) +1/(64) +1/(512) +1/(1024) +1/(4096) +1/(16384) +1/(32768) +1/(262144) +1/(1048576) )*2^29
999999999.999999446351872
ඒක තමයි. 999999999 හි වටිනාකම ඇත්ත වශයෙන්ම වේ
999999999.999999446351872
bc
-3.14 ද අවුල් සහගත බව ඔබට පරීක්ෂා කළ හැකිය . scale
සාධකයක් සැකසීමට අමතක නොකරන්න bc
.
පෙන්වන මුදල යනු දෘඩාංග තුළ ඇති දෙයයි. එය ගණනය කිරීමෙන් ඔබ ලබා ගන්නා අගය රඳා පවතින්නේ ඔබ නියම කළ පරිමාණය මත ය. මම scale
සාධකය 15 ට නියම කළෙමි . ගණිතමය වශයෙන්, අසීමිත නිරවද්යතාවයකින් එය 1,000,000,000 ක් බව පෙනේ.
මෙය බැලීමට තවත් ක්රමයක්: සංඛ්යා නිරූපණය කිරීම සඳහා බිටු 64 ක් භාවිතා කරයි. එහි ප්රති consequ ලයක් ලෙස 2 ** 64 = 18,446,744,073,709,551,616 ට වඩා වැඩි සංඛ්යාවක් නිශ්චිත සංඛ්යා නිරූපණය කළ නොහැක.
කෙසේ වෙතත්, ගණිතය පවසන්නේ දැනටමත් 0 සහ 1 අතර බොහෝ දශම සංඛ්යාවක් ඇති බවයි. IEE 754 මෙම බිටු 64 වඩා විශාල සංඛ්යා අවකාශයක් සඳහා NaN සහ +/- අනන්තය සඳහා කාර්යක්ෂමව භාවිතා කිරීම සඳහා කේතීකරණයක් අර්ථ දක්වයි, එබැවින් නිවැරදිව නිරූපණය කළ සංඛ්යා අතර හිඩැස් තිබේ ඉලක්කම් දළ වශයෙන් පමණි.
අවාසනාවට 0.3 හි පරතරයක් ඇත.
නිරවද්යතාවයේ ඉලක්කම් 8 ක් සමඟ මූලික දහයේ වැඩ කිරීම ගැන සිතන්න. දැයි පරීක්ෂා කරන්න
1/3 + 2 / 3 == 1
මෙය නැවත පැමිණෙන බව ඉගෙන ගන්න false
. මන්ද? හොඳයි, අපට ඇති තාත්වික සංඛ්යා ලෙස
1/3 = 0.333 .... සහ 2/3 = 0.666 ....
දශම ස්ථාන අටක කප්පාදු කිරීමෙන් අපට ලැබේ
0.33333333 + 0.66666666 = 0.99999999
ඇත්ත වශයෙන්ම 1.00000000
එය හරියටම වෙනස් වේ 0.00000001
.
ස්ථාවර බිටු සංඛ්යාවක් ඇති ද්විමය සංඛ්යා සඳහා තත්වය හරියටම සමාන වේ. තාත්වික සංඛ්යා ලෙස අපට තිබේ
1/10 = 0.0001100110011001100 ... (පාදම 2)
හා
1/5 = 0.0011001100110011001 ... (පාදම 2)
අපි මේවා බිටු හතකට කපා දැමුවහොත්, අපට ලැබෙනු ඇත
0.0001100 + 0.0011001 = 0.0100101
අනෙක් අතට,
3/10 = 0.01001100110011 ... (පාදම 2)
ඒවා බිටු හතකට කපා ඇත 0.0100110
, මේවා හරියටම වෙනස් වේ 0.0000001
.
මෙම සංඛ්යා සාමාන්යයෙන් විද්යාත්මක අංකනයෙහි ගබඩා කර ඇති නිසා නිශ්චිත තත්වය තරමක් සියුම් ය. උදාහරණයක් ලෙස, 1/10 ගබඩා කිරීම වෙනුවට 0.0001100
අපි එය වැනි දෙයක් ලෙස ගබඩා කළ හැකිය 1.10011 * 2^-4
, on ාතකය සහ මැන්ටිස්සා සඳහා අප කොපමණ බිට් ප්රමාණයක් වෙන් කර ඇත්ද යන්න මත පදනම්ව. ඔබගේ ගණනය කිරීම් සඳහා ඔබට කොපමණ සංඛ්යා නිරවද්යතාවයක් ලැබේද යන්න බලපායි.
මෙහි ප්රති shot ලය වනුයේ මෙම වටකුරු දෝෂ නිසා ඔබට පාවෙන ලක්ෂ්ය සංඛ්යා මත == භාවිතා කිරීමට අවශ්ය නොවේ. ඒ වෙනුවට, ඒවායේ වෙනසෙහි නිරපේක්ෂ වටිනාකම යම් ස්ථාවර කුඩා සංඛ්යාවට වඩා කුඩා දැයි ඔබට පරීක්ෂා කළ හැකිය.
පයිතන් 3.5 සිට ඔබට math.isclose()
ආසන්න සමානාත්මතාවය පරීක්ෂා කිරීම සඳහා ශ්රිතය භාවිතා කළ හැකිය :
>>> import math
>>> math.isclose(0.1 + 0.2, 0.3)
True
>>> 0.1 + 0.2 == 0.3
False
වර්තමාන පාවෙන ලක්ෂ්ය ක්රියාත්මක කිරීම් පිළිබඳ පොදු සාකච්ඡාවකට මෙම නූල ටිකක් දුරස් වී ඇති හෙයින්, ඒවායේ ගැටළු නිරාකරණය කිරීමේ ව්යාපෘති ඇති බව මම එකතු කරමි.
උදාහරණයක් ලෙස https://posithub.org/ දෙස බලන්න, එය පොසිට් (සහ එහි පූර්වගාමියා යුනම්) නම් අංකයක් පෙන්වන අතර එය බිටු අඩු ප්රමාණයක් සමඟ වඩා හොඳ නිරවද්යතාවයක් ලබා දෙන බවට පොරොන්දු වේ. මගේ අවබෝධය නිවැරදි නම්, එය ප්රශ්නයේ ඇති ගැටළු ද විසඳයි. ඉතා සිත්ගන්නා සුළු ව්යාපෘතියක් වන එය පිටුපස සිටින පුද්ගලයා ගණිත ian යෙක් වන ආචාර්ය ජෝන් ගුස්ටැෆ්සන් ය . සී / සී ++, පයිතන්, ජූලියා සහ සී # ( https://hastlayer.com/arithmetics ) හි බොහෝ සත්ය ක්රියාත්මක කිරීම් සහිතව සියල්ලම විවෘත මූලාශ්රයකි .
එය ඇත්තෙන්ම ඉතා සරල ය. ඔබට මූලික 10 පද්ධතියක් ඇති විට (අප වැනි), එයට ප්රකාශ කළ හැක්කේ පාදමේ ප්රධාන සාධකය භාවිතා කරන භාගයන් පමණි. 10 හි ප්රධාන සාධක 2 සහ 5 වේ. එබැවින් 1/2, 1/4, 1/5, 1/8 සහ 1/10 සියල්ලම පිරිසිදු ලෙස ප්රකාශ කළ හැකිය. මන්දයත් හරය සියල්ලම 10 හි ප්රධාන සාධක භාවිතා කරන බැවිනි. ඊට වෙනස්ව, 1 / 3, 1/6, සහ 1/7 සියල්ලම පුනරාවර්තන දශම වේ, මන්ද ඒවායේ හරය 3 හෝ 7 හි ප්රධාන සාධකය භාවිතා කරන බැවිනි. ද්විමය (හෝ පාදම 2) හි ඇති එකම ප්රධාන සාධකය 2. එබැවින් ඔබට භාග පමණක් පිරිසිදු ලෙස ප්රකාශ කළ හැකිය ප්රධාන සාධකයක් ලෙස 2 ක් පමණක් අඩංගු වේ. ද්විමය වශයෙන්, 1/2, 1/4, 1/8 සියල්ලම දශම ලෙස පිරිසිදු ලෙස ප්රකාශ වේ. 1/5 හෝ 1/10 යනු දශම සංඛ්යා පුනරාවර්තනය වේ. එබැවින් 0.1 සහ 0.2 (1/10 සහ 1/5) පදනම් 10 පද්ධතියක පිරිසිදු දශම, පරිගණකය ක්රියාත්මක වන පාදක 2 පද්ධතියේ දශම සංඛ්යා පුනරාවර්තනය කරයි. මෙම පුනරාවර්තන දශමයන් පිළිබඳව ඔබ ගණිතය කරන විට,
වැනි දශම සංඛ්යා 0.1
, 0.2
හා 0.3
ද්විමය හරියටම නියෝජනය නොවේ ඉපිලුම් ලක්ෂ්ය වර්ග කේතනය. සඳහා ආසන්න එකතුව 0.1
හා 0.2
සඳහා භාවිතා ආසන්න යතුරෙන් වෙනස් 0.3
නිසා ඇති බොරුව, 0.1 + 0.2 == 0.3
ලෙස මෙහි වඩාත් පැහැදිලිව දැක ගත හැක:
#include <stdio.h>
int main() {
printf("0.1 + 0.2 == 0.3 is %s\n", 0.1 + 0.2 == 0.3 ? "true" : "false");
printf("0.1 is %.23f\n", 0.1);
printf("0.2 is %.23f\n", 0.2);
printf("0.1 + 0.2 is %.23f\n", 0.1 + 0.2);
printf("0.3 is %.23f\n", 0.3);
printf("0.3 - (0.1 + 0.2) is %g\n", 0.3 - (0.1 + 0.2));
return 0;
}
ප්රතිදානය:
0.1 + 0.2 == 0.3 is false
0.1 is 0.10000000000000000555112
0.2 is 0.20000000000000001110223
0.1 + 0.2 is 0.30000000000000004440892
0.3 is 0.29999999999999998889777
0.3 - (0.1 + 0.2) is -5.55112e-17
මෙම ගණනය කිරීම් වඩාත් විශ්වාසදායක ලෙස ඇගයීමට නම්, පාවෙන ලක්ෂ්ය අගයන් සඳහා ඔබ දශම පාදක නිරූපණයක් භාවිතා කළ යුතුය. සී ප්රමිතිය මඟින් එවැනි වර්ග පෙරනිමියෙන් සඳහන් නොකරන නමුත් තාක්ෂණික වාර්තාවක විස්තර කර ඇති දිගුවක් ලෙස දැක්විය හැකිය .
මෙම _Decimal32
, _Decimal64
හා _Decimal128
වර්ග ඔබේ පද්ධතිය මත ලබා ගත හැකි විය හැකි (උදාහරණයක් ලෙස, සහ ගල්ෆ් මත සහාය තෝරාගත් ඉලක්ක , නමුත් Clang මත සහාය නොදක්වයි OS X මෙහෙයුම් පද්ධතිය ).
Math.sum (javascript) .... ක්රියාකරු ප්රතිස්ථාපනය
.1 + .0001 + -.1 --> 0.00010000000000000286
Math.sum(.1 , .0001, -.1) --> 0.0001
Object.defineProperties(Math, {
sign: {
value: function (x) {
return x ? x < 0 ? -1 : 1 : 0;
}
},
precision: {
value: function (value, precision, type) {
var v = parseFloat(value),
p = Math.max(precision, 0) || 0,
t = type || 'round';
return (Math[t](v * Math.pow(10, p)) / Math.pow(10, p)).toFixed(p);
}
},
scientific_to_num: { // this is from https://gist.github.com/jiggzson
value: function (num) {
//if the number is in scientific notation remove it
if (/e/i.test(num)) {
var zero = '0',
parts = String(num).toLowerCase().split('e'), //split into coeff and exponent
e = parts.pop(), //store the exponential part
l = Math.abs(e), //get the number of zeros
sign = e / l,
coeff_array = parts[0].split('.');
if (sign === -1) {
num = zero + '.' + new Array(l).join(zero) + coeff_array.join('');
} else {
var dec = coeff_array[1];
if (dec)
l = l - dec.length;
num = coeff_array.join('') + new Array(l + 1).join(zero);
}
}
return num;
}
}
get_precision: {
value: function (number) {
var arr = Math.scientific_to_num((number + "")).split(".");
return arr[1] ? arr[1].length : 0;
}
},
sum: {
value: function () {
var prec = 0, sum = 0;
for (var i = 0; i < arguments.length; i++) {
prec = this.max(prec, this.get_precision(arguments[i]));
sum += +arguments[i]; // force float to convert strings to number
}
return Math.precision(sum, prec);
}
}
});
පාවෙන දෝෂ මඟහරවා ගැනීම සඳහා ගණිතය වෙනුවට ක්රියාකරුවන් භාවිතා කිරීම මෙහි අදහසයි
Math.sum භාවිතා කිරීමේ නිරවද්යතාවය ස්වයංක්රීයව අනාවරණය කරයි
Math.sum ඕනෑම තර්ක ගණනාවක් පිළිගනී
පහත ප්රති results ල සලකා බලන්න:
error = (2**53+1) - int(float(2**53+1))
>>> (2**53+1) - int(float(2**53+1))
1
අපට පැහැදිලිවම බ්රේක්පොයින්ට් එකක් දැකිය හැකිය 2**53+1
- සියල්ල හොඳින් ක්රියාත්මක වන තුරු 2**53
.
>>> (2**53) - int(float(2**53))
0
මෙය සිදු වන්නේ ද්විත්ව නිරවද්යතා ද්විමය නිසා ය: IEEE 754 ද්විත්ව නිරවද්යතාව ද්විමය පාවෙන ලක්ෂ්ය ආකෘතිය: ද්විමය 64
ද්විත්ව නිරවද්යතාවයකින් යුත් පාවෙන ලක්ෂ්ය ආකෘතිය සඳහා විකිපීඩියා පිටුවෙන් :
ද්විත්ව නිරවද්යතාවයෙන් යුත් ද්විමය පාවෙන ලක්ෂ්යය පළාත් සභා වල බහුලව භාවිතා වන ආකෘතියක් වන අතර එහි ක්රියාකාරීත්වය සහ කලාප පළල පිරිවැය නොතකා තනි නිරවද්යතාවයකින් යුත් පාවෙන ලක්ෂ්යයට වඩා පුළුල් පරාසයක් ඇත. තනි නිරවද්යතාවයකින් යුත් පාවෙන ලක්ෂ්ය ආකෘතියක් මෙන්, එකම ප්රමාණයේ පූර්ණ සංඛ්යා ආකෘතියක් සමඟ සසඳන විට පූර්ණ සංඛ්යා සංඛ්යා වල නිරවද්යතාව එහි නොමැත. එය සාමාන්යයෙන් ද්විත්ව ලෙස හැඳින්වේ. IEEE 754 ප්රමිතිය ද්විමය 64 ඇති බව සඳහන් කරයි:
- සං bit ා බිට්: 1 බිට්
- On ාතකය: බිටු 11 යි
- සැලකිය යුතු නිරවද්යතාවය: බිටු 53 (පැහැදිලිව ගබඩා කර ඇති 52)
දී ඇති පක්ෂග්රාහී on ාතයක් සහ බිටු 52 ක භාගයක් සහිත දී ඇති 64-බිට් ද්වි-නිරවද්යතා දත්ත මගින් උපකල්පනය කරන ලද සැබෑ අගය
හෝ
එය මට පෙන්වා දීම ගැන @a_guest ට ස්තූතියි.
වෙනත් ප්රශ්නයක් මේ සඳහා අනුපිටපතක් ලෙස නම් කර ඇත:
C ++ හි, cout << x
නිදොස්කරණය කරන්නෙකු පෙන්වන අගයට වඩා වෙනස් වන්නේ x
ඇයි?
මෙම x
ප්රශ්නය තුළ ය float
විචල්ය.
එක් උදාහරණයක් වනු ඇත
float x = 9.9F;
නිදොස්කරණය පෙන්වයි 9.89999962
, ක්රියාකාරිත්වයේ ප්රතිදානය cout
වේ 9.9
.
පිළිතුර cout
පෙරනිමි නිරවද්යතාව float
6 ක් වන බැවින් එය දශම සංඛ්යා 6 ක් දක්වා විහිදේ.
යොමු කිරීම සඳහා මෙහි බලන්න