ভাসমান পয়েন্ট সংখ্যাগুলির তুলনামূলক তুলনা


10

আমার একটি সংখ্যাসূচক ফাংশন রয়েছে যা f(x, y)একটি দ্বৈত ভাসমান পয়েন্ট নম্বরটি ফিরিয়ে দেয় যা কিছু সূত্র কার্যকর করে এবং আমি তা পরীক্ষা করে দেখতে চাই যে এটি প্যারামিটারগুলির সমস্ত সংমিশ্রনের জন্য বিশ্লেষণাত্মক অভিব্যক্তির বিরুদ্ধে সঠিক xএবং yআমি আগ্রহী the বিশ্লেষণী ভাসমান পয়েন্ট সংখ্যা?

ধরা যাক দুটি সংখ্যা aএবং b। এখনও অবধি আমি নিশ্চিত হয়েছি যে পরম ( abs(a-b) < eps) পাশাপাশি আপেক্ষিক ( abs(a-b)/max(abs(a), abs(b)) < eps) ত্রুটি উভয়ই ইপ্সের চেয়ে কম are এই সংখ্যাটি সংখ্যাসূচক ভুলগুলি ধরবে যদিও সংখ্যাগুলি 1e-20 এর আশেপাশে বলা হয়।

তবে, আজ আমি একটি সমস্যা আবিষ্কার করেছি, সংখ্যাগত মান aএবং বিশ্লেষণযোগ্য মানটি bছিল:

In [47]: a                                                                     
Out[47]: 5.9781943146790832e-322

In [48]: b                                                                     
Out[48]: 6.0276008792632078e-322

In [50]: abs(a-b)                                                              
Out[50]: 4.9406564584124654e-324

In [52]: abs(a-b) / max(a, b)                                                  
Out[52]: 0.0081967213114754103

সুতরাং পরম ত্রুটি [50] (স্পষ্টতই) ছোট, তবে আপেক্ষিক ত্রুটি [52] বড় large সুতরাং আমি ভেবেছিলাম যে আমার প্রোগ্রামে একটি বাগ আছে। ডিবাগিংয়ের মাধ্যমে, আমি বুঝতে পারি যে এই সংখ্যাগুলি অস্বাভাবিক । এর মতো, যথাযথ তুলনামূলক তুলনা করতে আমি নিম্নলিখিত রুটিনটি লিখেছিলাম:

real(dp) elemental function rel_error(a, b) result(r)
real(dp), intent(in) :: a, b
real(dp) :: m, d
d = abs(a-b)
m = max(abs(a), abs(b))
if (d < tiny(1._dp)) then
    r = 0
else
    r = d / m
end if
end function

যেখানে tiny(1._dp)আমার কম্পিউটারে 2.22507385850720138E-308 প্রদান করে। এখন সবকিছু কাজ করে এবং আমি আপেক্ষিক ত্রুটি হিসাবে কেবল 0 পাই এবং সব ঠিক আছে। বিশেষত, উপরের আপেক্ষিক ত্রুটি [52] ভুল, এটি কেবলমাত্র ডেনরমাল সংখ্যার অপর্যাপ্ত নির্ভুলতার কারণে ঘটে। আমার rel_errorকার্যকারিতা বাস্তবায়ন সঠিক? আমি কি কেবল abs(a-b)যা ক্ষুদ্র (= ডেনরমাল) এর চেয়ে কম, এবং 0 ফেরত যাচ্ছি ? নাকি আমার মতো আরও কিছু সংমিশ্রণ পরীক্ষা করা উচিত max(abs(a), abs(b))?

আমি ঠিক জানতে চাই "সঠিক" উপায়টি কী।

উত্তর:


11

আপনি সরাসরি ব্যবহার denormals যাচাই করতে পারে isnormal()থেকে math.h(C99 বা পরে, POSIX.1 বা পরে)। ফরট্রানে, মডিউলটি ieee_arithmeticউপলব্ধ থাকলে আপনি ব্যবহার করতে পারেন ieee_is_normal()। অস্পষ্ট সাম্যতা সম্পর্কে আরও সুনির্দিষ্ট হওয়ার জন্য, আপনাকে ড্যানোরমালদের ভাসমান পয়েন্ট উপস্থাপনা বিবেচনা করতে হবে এবং ফলাফলগুলি যথেষ্ট ভাল হওয়ার জন্য আপনি কী বোঝাতে চাইছেন তা সিদ্ধান্ত নিতে হবে।

আরও উল্লেখযোগ্যভাবে, উভয় ফলাফল সঠিক বলে বিশ্বাস করার জন্য, আপনাকে অবশ্যই নিশ্চিত হতে হবে যে আপনি একটি মধ্যবর্তী পদক্ষেপে খুব বেশি অঙ্ক হারাতে পারেন নি। ডেনোরমালের সাথে গণনা সাধারণত অবিশ্বাস্য এবং আপনার অ্যালগোরিদম অভ্যন্তরীণভাবে পুনরুদ্ধার করে এড়ানো উচিত। আপনার অভ্যন্তরীণ স্কেলিং সফল হয়েছে তা নিশ্চিত করার জন্য, আমি ফোরট্রানের feenableexcept()সি 99 বা ieee_arithmeticমডিউল ব্যবহার করে ভাসমান পয়েন্ট ব্যতিক্রমগুলি সক্রিয় করার পরামর্শ দিচ্ছি ।

যদিও আপনি আপনার অ্যাপ্লিকেশনটিকে সিগন্যালটি ধরতে পারেন যা ভাসমান পয়েন্ট ব্যতিক্রমগুলিতে উত্থাপিত হয়, আমি যে সমস্ত কার্নেলগুলি হার্ডওয়্যার পতাকাটি পুনরায় সেট করার চেষ্টা করেছি তাই fetestexcept()কোনও কার্যকর ফলাফল ফিরে আসে না। যখন চালানো হয় তখন -fp_trapপিইটিএসসি প্রোগ্রামগুলি (ডিফল্টরূপে) যখন একটি ভাসমান বিন্দু ত্রুটি উত্থাপিত হয় তখন স্ট্যাক ট্রেস প্রিন্ট করবে তবে আপত্তিজনক রেখাটি সনাক্ত করবে না। আপনি যদি কোনও ডিবাগারে চালনা করেন তবে ডিবাগারটি হার্ডওয়্যার পতাকা সংরক্ষণ করে এবং আপত্তিকর ভাবটি ভেঙে দেয়। আপনি fetestexceptডিবাগার থেকে কল করে সঠিক কারণটি পরীক্ষা করতে পারেন যেখানে ফলাফলটি কিছুটা ধীরে ধীরে বা নীচের পতাকাগুলির মধ্যে রয়েছে (মানগুলি মেশিন অনুসারে পৃথক হতে পারে, দেখুন fenv.h; এই মানগুলি গ্লিবসি সহ x86-64)।

  • FE_INVALID = 0x1
  • FE_DIVBYZERO = 0x4
  • FE_OVERFLOW = 0x8
  • FE_UNDERFLOW = 0x10
  • FE_INEXACT = 0x20

চমৎকার উত্তরের জন্য ধন্যবাদ। অ্যাসিপটোটিক শাসন ব্যবস্থায় আমি যে বিশ্লেষণাত্মক অভিব্যক্তিটির সাথে তুলনা করি তা exp(log_gamma(m+0.5_dp) - (m+0.5_dp)*log(t)) / 2মি = 234, টি = 2000 এর জন্য। আমি বাড়ার সাথে সাথে এটি শূন্যে চলে যায় m। আমি নিশ্চিত করতে চাই যে আমার সংখ্যাসূচক রুটিনগুলি "সঠিক" নম্বরগুলি (শূন্য ফিরে আসতে পুরোপুরি ঠিক আছে) কমপক্ষে 12 টি উল্লেখযোগ্য সংখ্যায় ফিরে আসে। সুতরাং যদি গণনাটি একটি অস্বীকৃত নম্বর দেয় তবে তা কেবল শূন্য এবং কোনও সমস্যা হওয়া উচিত নয়। সুতরাং তুলনার রুটিনকে এর বিপরীতে শক্ত হওয়া দরকার to
Ondřej Čertík

5

ডোনাল্ড নথের কাছে "দ্য আর্ট অফ কম্পিউটার প্রোগ্রামিং" এর ভলিউম 2 "সেমিনিমেরিক্যাল অ্যালগরিদম" এর ভাসমান পয়েন্ট তুলনা অ্যালগরিদমের প্রস্তাব রয়েছে। এটি সি দ্বারা কার্যকর করা হয়েছিল। Belding (দেখুন fcmp প্যাকেজ ) এবং পাওয়া যায় GSL


2
এখানে আমার ফোর্টরান বাস্তবায়ন: gist.github.com/3776847 , লক্ষ্য করুন যে এতে যেভাবেই হোক আমি ডেনারমাল সংখ্যাগুলি স্পষ্টভাবে পরিচালনা করতে হবে need অন্যথায় আমি মনে করি এটি আপেক্ষিক ত্রুটির তুলনায় অনেকটা সমান, পার্থক্য কেবল এটি করার পরিবর্তে abs(a-b)/max(a, b) < epsআমরা করি abs(a-b)/2**exponent(max(a, b)) < eps, যা বেশিরভাগ ক্ষেত্রেই ম্যান্টিসাকে ফেলে দেয় max(a, b), তাই আমার মতে পার্থক্যটি নগণ্য।
ওঁদেজ এর্তিক

5

অনুকূল বৃত্তাকার অস্বীকৃতিযুক্ত সংখ্যার প্রকৃতপক্ষে একটি উচ্চ আপেক্ষিক ত্রুটি থাকতে পারে। (এটিকে শূন্যে ফ্লাশ করা এখনও একে আপেক্ষিক ত্রুটি বলে আখ্যায়িত করা বিভ্রান্তিকর)

তবে শূন্যের কাছাকাছি, আপেক্ষিক এরোগুলি গণনা করা অর্থহীন।

সুতরাং, আপনি অস্বীকৃত সংখ্যায় পৌঁছানোর আগেই আপনার সম্ভবত নিখুঁত নির্ভুলতার দিকে যাওয়া উচিত (যাকে আপনি এই ক্ষেত্রে গ্যারান্টি দিতে চান)।

Yএক্স|Y-এক্স|একটিগুলিএকটি+ +Rএকটি*সর্বোচ্চ(|এক্স|,|Y|)

তারপরে আপনার কোডের ব্যবহারকারীরা তাদের সত্যতা কতটা নির্ভুলতার সাথে অবিকল জানেন।


আপনি কি নিশ্চিত যে শূন্যের নিকটে আপেক্ষিক ত্রুটিগুলি গণনা করা অর্থহীন? আমি বিশ্বাস করি কেবলমাত্র যদি সঠিকতার ক্ষতি হয় (তবে যে কোনও কারণে) is উদাহরণস্বরূপ যদি কিছু সংখ্যাসূচক সমস্যার কারণে x <1e-150 এর সঠিকতার ক্ষতি হয় (যেমন দুটি বড় সংখ্যা বিয়োগ করা) তবে আপনি ঠিক বলেছেন right আমার ক্ষেত্রে তবে সংখ্যাগুলি শূন্যের নিচে সমস্ত দিকেই যথাযথ বলে মনে হচ্ছে, যখন এটি অস্বীকৃত সংখ্যাগুলি হিট করে। সুতরাং আমার ক্ষেত্রে অ্যাব্যাস্যাক = 1e-320 বা ততোধিক এবং আমি abs(a-b) < tiny(1._dp)উপরে যেমন করলাম ঠিক তেমন পরীক্ষা করতে পারি।
ওয়ান্ডেজ এর্ত্তিক

@ অ্যান্ডেজিজারটেক: সেক্ষেত্রে 1e-150 প্রতি 1e-300 দ্বারা প্রতিস্থাপন করুন বা যা যা বেউন্ড যাচাই করতে পারবেন। যে কোনও ক্ষেত্রে শূন্যের খুব কাছাকাছি সময়ে আপনি একটি নিখুঁত ত্রুটি করেন এবং আপেক্ষিক ত্রুটি শূন্য হিসাবে ঘোষণা করার পরিবর্তে আপনার ত্রুটি দাবিটি এটি প্রতিফলিত করে।
আর্নল্ড নিউমায়ার

আমি দেখি. আমি যাচাই করতে পারি, যে সমস্ত সংখ্যার চেয়ে বেশি সংখ্যার জন্য কাজ করে tiny(1._dp)=2.22507385850720138E-308(আমি আমার আগের মন্তব্যে ভুল করেছি, এটি 2e-308, 1e-320 নয়)। সুতরাং এটি আমার পরম ত্রুটি। তারপরে আমার আপেক্ষিক ত্রুটি তুলনা করা দরকার। আমি আপনার বক্তব্য দেখুন, আমি মনে করি আপনি ঠিক বলেছেন। ধন্যবাদ!
ওন্ডেজ এজাতক

1
@ OndřejČertík: absacc দেওয়া অতিরিক্ত আপেক্ষিক ত্রুটি খুঁজে পেতে, সর্বোচ্চ নিরীক্ষণ । |Y-এক্স|-একটিগুলিএকটিসর্বোচ্চ(|এক্স|,|Y|)
আর্নল্ড নিউমায়ার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.