শান্ত এনএএন এবং সিএনএল সিএএনএনের মধ্যে পার্থক্য কী?


106

আমি ভাসমান-পয়েন্ট সম্পর্কে পড়েছি এবং আমি বুঝতে পারি যে অপারেশনগুলির ফলে NaN এর ফলাফল হতে পারে। তবে আমি বুঝতে পারি না এগুলি ঠিক কী। তাদের মধ্যে পার্থক্য কী?

সি ++ প্রোগ্রামিংয়ের সময় কোনটি তৈরি করা যায়? প্রোগ্রামার হিসাবে, আমি কি এমন একটি প্রোগ্রাম লিখতে পারি যা একটি এসএনএএন-এর কারণ হয়?

উত্তর:


72

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

সি ++ 11 কয়েক ভাষা যোগ করা ফ্লোটিং পয়েন্ট পরিবেশ উপর নিয়ন্ত্রণ এবং প্রদান করে মান তৈরি করতে আচার-ব্যবহার ও Nans জন্য পরীক্ষার । তবে নিয়ন্ত্রণগুলি কার্যকরভাবে প্রয়োগ করা হচ্ছে কিনা তা মানসম্মত নয় এবং ভাসমান-পয়েন্ট ব্যতিক্রমগুলি সাধারণত স্ট্যান্ডার্ড সি ++ ব্যতিক্রমগুলির মতো একইভাবে ধরা পড়ে না।

পসিক্স / ইউনিক্স সিস্টেমগুলিতে, সাধারণত ভাসমান পয়েন্ট ব্যতিক্রমগুলি SIGFPE এর জন্য কোনও হ্যান্ডলার ব্যবহার করে ধরা হয় ।


36
এটিতে যুক্ত করা: সাধারণত, ডিএনবিগ করার জন্য NaN (sNaN) এর সিগন্যালিংয়ের উদ্দেশ্য। উদাহরণস্বরূপ, ভাসমান-পয়েন্ট অবজেক্টগুলি এসএনএএন-তে শুরু হতে পারে। তারপরে, প্রোগ্রামটি ব্যবহারের আগে যদি সেগুলির মধ্যে একটিতে ব্যর্থ হয়, যখন একটি পাটিগণিত অপারেশনে প্রোগ্রামটি এসএনএএন ব্যবহার করে তখন একটি ব্যতিক্রম ঘটে। কোনও প্রোগ্রাম অজান্তেই একটি এসএনএএন উত্পাদন করে না; কোনও সাধারণ ক্রিয়াকলাপ এসএনএএন উত্পাদন করে না। এগুলি কেবলমাত্র একটি গাণিতিকের ফলাফল হিসাবে নয়, একটি সিগন্যাল এনএএন থাকার উদ্দেশ্যে তৈরি করা হয়েছিল।
এরিক পোস্টপিসিল

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

@ ওয়ার্ডিটার আপনাকে ধন্যবাদ, তবে কেবল নাজোর পার্থক্যই হ'ল এক্সপিশন উত্পন্ন করছে বা না।
জালাল জাবেরি

@ এরিকপোস্টপিসিল প্রশ্নটির দ্বিতীয় খণ্ডে মনোযোগ দেওয়ার জন্য আপনাকে ধন্যবাদ।
জালাল জাবেরি

@ জলাল জাবেরি হ্যাঁ, ব্যতিক্রমটি মূল পার্থক্য
wrdieter

40

কিউএনএএন এবং এসএনএএন পরীক্ষামূলকভাবে দেখতে কেমন?

আসুন প্রথমে শিখি কীভাবে সনাক্ত করতে হয় আমাদের কাছে একটি এসএনএএন বা কিউএনএন রয়েছে।

আমি সি এর পরিবর্তে এই উত্তরে সি ++ ব্যবহার করব কারণ এটি সুবিধাজনক অফার করে std::numeric_limits::quiet_NaNএবং std::numeric_limits::signaling_NaNযা আমি সি তে সুবিধাজনকভাবে খুঁজে পাই না।

তবে কোনও NaN এসএনএন বা কিউএনএন হলে শ্রেণিবদ্ধ করার জন্য আমি কোনও ফাংশনটি খুঁজে পাইনি, সুতরাং আসুন আমরা কেবলমাত্র NaN কাঁচা বাইটগুলি প্রিন্ট আউট করব:

main.cpp

#include <cassert>
#include <cstring>
#include <cmath> // nanf, isnan
#include <iostream>
#include <limits> // std::numeric_limits

#pragma STDC FENV_ACCESS ON

void print_float(float f) {
    std::uint32_t i;
    std::memcpy(&i, &f, sizeof f);
    std::cout << std::hex << i << std::endl;
}

int main() {
    static_assert(std::numeric_limits<float>::has_quiet_NaN, "");
    static_assert(std::numeric_limits<float>::has_signaling_NaN, "");
    static_assert(std::numeric_limits<float>::has_infinity, "");

    // Generate them.
    float qnan = std::numeric_limits<float>::quiet_NaN();
    float snan = std::numeric_limits<float>::signaling_NaN();
    float inf = std::numeric_limits<float>::infinity();
    float nan0 = std::nanf("0");
    float nan1 = std::nanf("1");
    float nan2 = std::nanf("2");
    float div_0_0 = 0.0f / 0.0f;
    float sqrt_negative = std::sqrt(-1.0f);

    // Print their bytes.
    std::cout << "qnan "; print_float(qnan);
    std::cout << "snan "; print_float(snan);
    std::cout << " inf "; print_float(inf);
    std::cout << "-inf "; print_float(-inf);
    std::cout << "nan0 "; print_float(nan0);
    std::cout << "nan1 "; print_float(nan1);
    std::cout << "nan2 "; print_float(nan2);
    std::cout << " 0/0 "; print_float(div_0_0);
    std::cout << "sqrt "; print_float(sqrt_negative);

    // Assert if they are NaN or not.
    assert(std::isnan(qnan));
    assert(std::isnan(snan));
    assert(!std::isnan(inf));
    assert(!std::isnan(-inf));
    assert(std::isnan(nan0));
    assert(std::isnan(nan1));
    assert(std::isnan(nan2));
    assert(std::isnan(div_0_0));
    assert(std::isnan(sqrt_negative));
}

সংকলন এবং চালান:

g++ -ggdb3 -O3 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

আমার x86_64 মেশিনে আউটপুট:

qnan 7fc00000
snan 7fa00000
 inf 7f800000
-inf ff800000
nan0 7fc00000
nan1 7fc00001
nan2 7fc00002
 0/0 ffc00000
sqrt ffc00000

আমরা কিউএমইউ ব্যবহারকারীর মোডের সাহায্যে আর্চ 64 এ প্রোগ্রামটি চালাতে পারি:

aarch64-linux-gnu-g++ -ggdb3 -O3 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
qemu-aarch64 -L /usr/aarch64-linux-gnu/ main.out

এবং এটি হুবহু একই আউটপুট উত্পাদন করে যে একাধিক খিলান ঘনিষ্ঠভাবে আইইইই 754 বাস্তবায়ন পরামর্শ দেয়।

এই মুহুর্তে, আপনি যদি আইইইই 754 ভাসমান পয়েন্ট সংখ্যাগুলির কাঠামোর সাথে পরিচিত না হন তবে একবার নজর দিন: একটি সাধারণ অস্থায়ী পয়েন্ট সংখ্যাটি কী?

বাইনারি উপরের কিছু মান রয়েছে:

     31
     |
     | 30    23 22                    0
     | |      | |                     |
-----+-+------+-+---------------------+
qnan 0 11111111 10000000000000000000000
snan 0 11111111 01000000000000000000000
 inf 0 11111111 00000000000000000000000
-inf 1 11111111 00000000000000000000000
-----+-+------+-+---------------------+
     | |      | |                     |
     | +------+ +---------------------+
     |    |               |
     |    v               v
     | exponent        fraction
     |
     v
     sign

এই পরীক্ষা থেকে আমরা পর্যবেক্ষণ করি:

  • qNaN এবং sNaN 22 বিট দ্বারা কেবল পৃথক বলে মনে হচ্ছে শান্ত 1, এবং 0 এর অর্থ সংকেত

  • ইনফিনিটিগুলি = 0 0xFF এর সাথেও বেশ মিল, তবে তাদের ভগ্নাংশ == 0 রয়েছে।

    এই কারণে, NaNs 21 থেকে 1 বিট সেট করতে হবে, অন্যথায় sNaN কে ইতিবাচক অনন্ত থেকে আলাদা করা সম্ভব হবে না!

  • nanf() বিভিন্ন বিভিন্ন NaN উত্পাদন করে, তাই একাধিক সম্ভাব্য এনকোডিং অবশ্যই থাকতে হবে:

    7fc00000
    7fc00001
    7fc00002
    

    যেহেতু nan0একই std::numeric_limits<float>::quiet_NaN(), তাই আমরা অনুমান করি যে তারা সবাই আলাদা আলাদা শান্ত এনএন।

    C11 N1570 মান খসড়া নিশ্চিত করে যে nanf()শান্ত Nans উত্পন্ন, কারণ nanfসামনে থেকে strtodএবং 7.22.1.3 "strtod, strtof এবং strtold ফাংশন" বলেছেন:

    একটি অক্ষর অনুক্রম এনএএন বা এনএএন (এন-চর-সিকোয়েন্স অপ্ট )টিকে একটি শান্ত নেএন হিসাবে ব্যাখ্যা করা হয়, যদি রিটার্ন টাইপের ক্ষেত্রে সমর্থন করা হয়, অন্যথায় বিষয় সিকোয়েন্স অংশের মতো যার প্রত্যাশিত ফর্ম নেই; এন-চর ক্রমের অর্থ বাস্তবায়ন-সংজ্ঞায়িত। 293)

আরো দেখুন:

ম্যানুয়ালগুলিতে qNaN এবং sNaN দেখতে কেমন?

আইইইই 754 2008 সুপারিশ করে যে (TODO বাধ্যতামূলক বা alচ্ছিক?):

  • কাফের == 0xFF এবং ভগ্নাংশ সহ যে কোনও কিছুই! = 0 একটি NaN
  • এবং সর্বাধিক ভগ্নাংশ বিট এসএনএএন থেকে কিউএনএনকে পার্থক্য করে

তবে এটি এনএএন থেকে অনন্তের পার্থক্যের তুলনায় কোন বিটকে বেশি পছন্দ করে তা বলে মনে হচ্ছে না।

6.2.1 "বাইনারি ফর্ম্যাটগুলিতে NaN এনকোডিংস" বলেছেন:

এই সাবক্লেজটি NaNs এর এনকোডিংগুলিকে বিট স্ট্রিং হিসাবে নির্দিষ্ট করে যখন তারা অপারেশনের ফলাফল হয়। এনকোড করা অবস্থায়, সমস্ত এনএএন-এর এনএনড হিসাবে এনএনডিং সনাক্তকরণের জন্য প্রয়োজনীয় একটি চিহ্ন বিট এবং বিটের একটি প্যাটার্ন থাকে এবং এটি তার ধরণের (এসএনএএনএন বনাম কিউএনএন) নির্ধারণ করে। বাকি বিটগুলি, যা পিছনে তাত্পর্যপূর্ণ ক্ষেত্রের মধ্যে রয়েছে, পে-লোডকে এনকোড করে দেয় যা ডায়াগনস্টিক তথ্য হতে পারে (উপরে দেখুন)। 34

সমস্ত বাইনারি ন্যান বিট স্ট্রিংগুলিতে পক্ষপাতদুষ্ট এক্সপোনেন্ট ফিল্ডের সমস্ত বিট 1 সেট করা আছে (দেখুন 3.4)। একটি নিখুঁত এনএইন বিট স্ট্রিংটি অনুগামী তাত্পর্যপূর্ণ ক্ষেত্র টি এর প্রথম বিট (ডি 1) এর সাথে এনকোড করা উচিত 1. অনুচরনের তাত্পর্যপূর্ণ ক্ষেত্রটি 0 হয়, অনুগ্রহ থেকে NaN পার্থক্য করার জন্য অনুসরণযোগ্য তাত্পর্য ক্ষেত্রের অন্য কিছু বিট অবশ্যই শূন্য নয়। স্রেফ বর্ণিত পছন্দের এনকোডিং-এ, ডি -1 থেকে 1 সেট করে একটি সিগন্যালিং এনএএন শান্ত করা হবে, টি-র অবশিষ্ট বিটগুলি অপরিবর্তিত রেখে। বাইনারি ফর্ম্যাটগুলির জন্য, পে-লোড পি-enc 2 টি অনুমানের ক্ষেত্রের তাত্পর্যপূর্ণ ক্ষেত্রের কমপক্ষে উল্লেখযোগ্য বিটগুলিতে এনকোড থাকে

ইন্টেল 64 এবং IA-32 আর্কিটেকচারের সফটওয়্যার উন্নয়নকারীর ম্যানুয়াল - ভলিউম 1 বেসিক আর্কিটেকচার - 253665-056US সেপ্টেম্বর 2015 4.8.3.4 "Nans" নিশ্চিত করে যে এক্স 86 সর্বোচ্চ ভগ্নাংশ অল্পে NaN এবং sNaN পার্থক্য দ্বারা আইইইই 754 অনুসরণ করে:

আইএ -32 আর্কিটেকচার NaNs এর দুটি শ্রেণি সংজ্ঞায়িত করে: শান্ত NaNs (QNaNs) এবং NaNs (SNaNs) সিগন্যাল করে। একটি কিউএনএএন হ'ল একটি এনএএন যা সবচেয়ে উল্লেখযোগ্য ভগ্নাংশ বিট সেট করে একটি এসএনএনএন একটি এনএএনএন যেখানে সবচেয়ে উল্লেখযোগ্য ভগ্নাংশ বিট পরিষ্কার হয়।

এবং তাই এআরএম আর্কিটেকচার রেফারেন্স ম্যানুয়াল - এআরএমভি 8, এআরএমভি 8-একটি আর্কিটেকচার প্রোফাইলের জন্য - ডিডিআই 0487C.a এ 1.4.3 "একক-নির্ভুলতা ভাসমান-বিন্যাস ফর্ম্যাট":

fraction != 0: মানটি একটি NaN, এবং হয় শান্ত NaN বা সিগন্যালিং এনএএন। দুই ধরণের NaN তাদের উল্লেখযোগ্য ভগ্নাংশ বিট, বিট [22] দ্বারা পৃথক করা হয়েছে:

  • bit[22] == 0: এনএএন একটি সিগন্যালিং এনএন N সাইন বিট যে কোনও মান নিতে পারে এবং বাকি ভগ্নাংশ বিটগুলি সমস্ত শূন্য ছাড়া কোনও মান নিতে পারে।
  • bit[22] == 1: দ্য এনএন একটি শান্ত ন্যান। সাইন বিট এবং অবশিষ্ট ভগ্নাংশ বিটগুলি কোনও মান নিতে পারে।

কিউএনএনএস এবং এসএনএএনএস কীভাবে উত্পন্ন হয়?

QNaN এবং sNaN এর মধ্যে একটি প্রধান পার্থক্য হ'ল:

  • qNaN অদ্ভুত মান সহ নিয়মিত অন্তর্নির্মিত (সফ্টওয়্যার বা হার্ডওয়্যার) গাণিতিক ক্রিয়াকলাপ দ্বারা উত্পাদিত হয়
  • এসএনএএন কখনই অন্তর্নির্মিত ক্রিয়াকলাপের মাধ্যমে উত্পন্ন হয় না, এটি কেবল প্রোগ্রামারদের দ্বারা স্পষ্টভাবে যুক্ত করা যেতে পারে, যেমন std::numeric_limits::signaling_NaN

আমি এর জন্য স্পষ্ট আইইইই 754 বা সি 11 উদ্ধৃতি খুঁজে পাইনি, তবে sNaNs জেনারেট করে এমন কোনও বিল্ট-ইন অপারেশনও খুঁজে পাচ্ছি না ;-)

ইন্টেল ম্যানুয়ালটি 4.8.3.4 "NaNs" এ এই নীতিটি পরিষ্কারভাবে জানিয়েছে:

এসএনএএনগুলি সাধারণত একটি ব্যতিক্রম হ্যান্ডলারকে ফাঁদে ফেলতে বা অনুরোধ করতে ব্যবহৃত হয়। সেগুলি অবশ্যই সফ্টওয়্যার দ্বারা প্রবেশ করানো উচিত; অর্থাৎ, প্রসেসর কোনও ভাসমান-পয়েন্ট অপারেশনের ফলস্বরূপ কোনও এসএনএএন জেনারেট করে না।

এটি আমাদের উদাহরণ থেকে দেখা যায় যেখানে উভয়ই:

float div_0_0 = 0.0f / 0.0f;
float sqrt_negative = std::sqrt(-1.0f);

ঠিক একই বিট উত্পাদন std::numeric_limits<float>::quiet_NaN()

এই দুটি অপারেশনই সিঙ্গেল x86 এ্যাসেম্বলি নির্দেশের সাথে সংকলন করে যা হার্ডওয়ারে সরাসরি QNaN উৎপন্ন করে (টোডো জিডিবি দিয়ে কনফার্ম করে)।

কিউএনএএন এবং এসএনএএন আলাদাভাবে কী করে?

এখন যেহেতু আমরা জানি যে কীএনএএন এবং এসএনএএনগুলি দেখতে কীভাবে, এবং কীভাবে সেগুলি চালিত করতে হয়, আমরা শেষ পর্যন্ত এসএনএএনগুলি তাদের জিনিসটি করার চেষ্টা করতে এবং কিছু প্রোগ্রাম উড়িয়ে দেওয়ার জন্য প্রস্তুত!

সুতরাং আরও অ্যাডো ছাড়া:

blow_up.cpp

#include <cassert>
#include <cfenv>
#include <cmath> // isnan
#include <iostream>
#include <limits> // std::numeric_limits
#include <unistd.h>

#pragma STDC FENV_ACCESS ON

int main() {
    float snan = std::numeric_limits<float>::signaling_NaN();
    float qnan = std::numeric_limits<float>::quiet_NaN();
    float f;

    // No exceptions.
    assert(std::fetestexcept(FE_ALL_EXCEPT) == 0);

    // Still no exceptions because qNaN.
    f = qnan + 1.0f;
    assert(std::isnan(f));
    if (std::fetestexcept(FE_ALL_EXCEPT) == FE_INVALID)
        std::cout << "FE_ALL_EXCEPT qnan + 1.0f" << std::endl;

    // Now we can get an exception because sNaN, but signals are disabled.
    f = snan + 1.0f;
    assert(std::isnan(f));
    if (std::fetestexcept(FE_ALL_EXCEPT) == FE_INVALID)
        std::cout << "FE_ALL_EXCEPT snan + 1.0f" << std::endl;
    feclearexcept(FE_ALL_EXCEPT);

    // And now we enable signals and blow up with SIGFPE! >:-)
    feenableexcept(FE_INVALID);
    f = qnan + 1.0f;
    std::cout << "feenableexcept qnan + 1.0f" << std::endl;
    f = snan + 1.0f;
    std::cout << "feenableexcept snan + 1.0f" << std::endl;
}

সংকলন করুন, চালান এবং প্রস্থান স্থিতি পান:

g++ -ggdb3 -O0 -Wall -Wextra -pthread -std=c++11 -pedantic-errors -o blow_up.out blow_up.cpp -lm -lrt
./blow_up.out
echo $?

আউটপুট:

FE_ALL_EXCEPT snan + 1.0f
feenableexcept qnan + 1.0f
Floating point exception (core dumped)
136

নোট করুন যে এই আচরণটি কেবলমাত্র -O0জিসিসি 8.2 তে ঘটে : এর সাথে -O3, জিসিসি আমাদের সমস্ত এসএনএএন অপারেশনকে প্রাক-গণনা করে এবং অনুকূলিত করে! আমি এটি নিশ্চিত না যে এটির প্রতিরোধের কোনও মানক উপায় আছে কিনা।

সুতরাং আমরা এই উদাহরণ থেকে অনুমান যে:

  • snan + 1.0কারণ FE_INVALID, কিন্তু qnan + 1.0না

  • লিনাক্স কেবল তখনই সিগন্যাল উত্পন্ন করে যদি এটি সক্ষম হয় feenableexept

    এটি একটি গ্লাবসি এক্সটেনশন, আমি কোনও মানক হিসাবে এটি করার কোনও উপায় খুঁজে পাইনি।

সিগন্যালটি ঘটলে এটি সিপিইউ হার্ডওয়্যার নিজেই একটি ব্যতিক্রম উত্থাপন করে, যা লিনাক্স কার্নেল সিগন্যালের মাধ্যমে অ্যাপ্লিকেশনটি পরিচালনা ও অবহিত করে।

ফলাফল যে ব্যাশ ছাপে Floating point exception (core dumped), এবং প্রস্থান অবস্থা 136, যা অনুরূপ সংকেত 136 - 128 == 8, যা অনুযায়ী:

man 7 signal

হয় SIGFPE

দ্রষ্টব্য SIGFPEএটি একই সংকেত যা আমরা পাই যদি একটি পূর্ণসংখ্যা 0 দ্বারা ভাগ করার চেষ্টা করি তবে:

int main() {
    int i = 1 / 0;
}

যদিও পূর্ণসংখ্যার জন্য:

  • কোনও কিছুর শূন্য দ্বারা ভাগ করা সংকেত উত্থাপন করে, যেহেতু পূর্ণসংখ্যায় কোনও অনন্ত প্রতিনিধিত্ব নেই
  • সিগন্যালটি এটি প্রয়োজন ছাড়াই ডিফল্টভাবে ঘটে feenableexcept

কীভাবে SIGFPE পরিচালনা করবেন?

যদি আপনি কেবল একটি হ্যান্ডলার তৈরি করেন যা সাধারণত ফিরে আসে তবে এটি একটি অসীম লুপকে নিয়ে যায়, কারণ হ্যান্ডলারটি ফিরে আসার পরে বিভাগটি আবার ঘটে! এটি জিডিবি দিয়ে যাচাই করা যেতে পারে।

একমাত্র উপায় হ'ল যেমন দেখানো হয়েছে তেমন ব্যবহার করা setjmpএবং longjmpঅন্য কোথাও লাফানো: সি হ্যান্ডেল সংকেত SIGFPE এবং কার্যকর করা চালিয়ে যাওয়া execution

এসএনএএন-এর কয়েকটি বাস্তব বিশ্বের অ্যাপ্লিকেশন কী কী?

মোটামুটি সত্যই, আমি এখনও এসএনএএনএসের জন্য একটি দরকারী দরকারী ব্যবহারের বিষয়টি বুঝতে পারি নি, এটিতে এখানে জিজ্ঞাসা করা হয়েছে: এনএএন সিগন্যাল করার উপযোগিতা?

এসএনএএনগুলি বিশেষত অকেজো বলে মনে হয় কারণ আমরা প্রাথমিক অবৈধ ক্রিয়াকলাপগুলি সনাক্ত করতে পারি (যা 0.0f/0.0f) এর সাথে কিউএনএএন তৈরি করে feenableexcept: এটি প্রদর্শিত হয় যে snanআরও বেশি ক্রিয়াকলাপের জন্য ত্রুটি উত্থাপন qnanকরে, যেমন ( qnan + 1.0f)।

যেমন:

main.c

#define _GNU_SOURCE
#include <fenv.h>
#include <stdio.h>

int main(int argc, char **argv) {
    (void)argv;
    float f0 = 0.0;

    if (argc == 1) {
        feenableexcept(FE_INVALID);
    }
    float f1 = 0.0 / f0;
    printf("f1 %f\n", f1);

    feenableexcept(FE_INVALID);
    float f2 = f1 + 1.0;
    printf("f2 %f\n", f2);
}

সংকলন:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c -lm

তারপরে:

./main.out

দেয়:

Floating point exception (core dumped)

এবং:

./main.out  1

দেয়:

f1 -nan
f2 -nan

আরও দেখুন: সি ++ এ কীভাবে কোনও NAN ট্রেস করবেন

সিগন্যাল পতাকাগুলি কী কী এবং সেগুলি কীভাবে পরিচালিত হয়?

সবকিছুই সিপিইউ হার্ডওয়্যারের মধ্যে প্রয়োগ করা হয়।

পতাকাগুলি কিছু রেজিস্টারে থাকে এবং তাই কিছুটা বলে যে কোনও ব্যতিক্রম / সংকেত উত্থাপন করা উচিত কিনা।

এই নিবন্ধগুলি বেশিরভাগ আর্চ থেকে ব্যবহারকারীল্যান্ড থেকে অ্যাক্সেসযোগ্য

গ্লিবসি ২.২৯ কোডের এই অংশটি আসলে বুঝতে খুব সহজ!

উদাহরণস্বরূপ, fetestexceptx86_86 এর জন্য sysdeps / x86_64 / fpu / ftestexcept.c এ প্রয়োগ করা হয়েছে :

#include <fenv.h>

int
fetestexcept (int excepts)
{
  int temp;
  unsigned int mxscr;

  /* Get current exceptions.  */
  __asm__ ("fnstsw %0\n"
       "stmxcsr %1" : "=m" (*&temp), "=m" (*&mxscr));

  return (temp | mxscr) & excepts & FE_ALL_EXCEPT;
}
libm_hidden_def (fetestexcept)

সুতরাং আমরা তাত্ক্ষণিকভাবে দেখতে পাচ্ছি যে নির্দেশাবলীর ব্যবহারগুলি হ'ল stmxcsr"স্টোর এমএক্সসিএসআর রেজিস্টার স্টেট"।

এবং sysdeps / x86_64 / fpu / feenablxcpt.cfeenableexcept এ প্রয়োগ করা হয়েছে :

#include <fenv.h>

int
feenableexcept (int excepts)
{
  unsigned short int new_exc, old_exc;
  unsigned int new;

  excepts &= FE_ALL_EXCEPT;

  /* Get the current control word of the x87 FPU.  */
  __asm__ ("fstcw %0" : "=m" (*&new_exc));

  old_exc = (~new_exc) & FE_ALL_EXCEPT;

  new_exc &= ~excepts;
  __asm__ ("fldcw %0" : : "m" (*&new_exc));

  /* And now the same for the SSE MXCSR register.  */
  __asm__ ("stmxcsr %0" : "=m" (*&new));

  /* The SSE exception masks are shifted by 7 bits.  */
  new &= ~(excepts << 7);
  __asm__ ("ldmxcsr %0" : : "m" (*&new));

  return old_exc;
}

সি স্ট্যান্ডার্ড কিউএনএএন বনাম এসএনএএন সম্পর্কে কী বলে?

C11 N1570 মান খসড়া স্পষ্টভাবে বলছেন যে মান F.2.1 "অসীমতার সাইনড শূন্য, এবং Nans" তাদের মধ্যে পার্থক্য করে না:

1 এই স্পেসিফিকেশন NaN গুলি সিগন্যাল করার আচরণ সংজ্ঞায়িত করে না। এটি শান্ত NaNs বোঝাতে সাধারণত NaN শব্দটি ব্যবহার করে। নন এবং ইনফিনিটি ম্যাক্রোগুলি এবং ন্যান ফাংশনগুলি <math.h>আইইসি 60559 ন্যান এবং ইনফিনিটিগুলির জন্য উপাধি সরবরাহ করে।

উবুন্টু 18.10, জিসিসি 8.2 তে পরীক্ষিত। গিটহাব উজানের ধারা:


en.wikipedia.org/wiki/IEEE_754#Interchange_formats পয়েন্ট আউট আইইইই-754 নিছক যে প্রস্তাব দেওয়া যে 0 একটি ভাল বাস্তবায়ন পছন্দ Nans সংকেত জন্য, এটি একটি অনন্ত (significand = 0) উপার্জন ঝুঁকি ছাড়া একটি NaN শান্ত করে অনুমতি দেয়। দৃশ্যত এটি মানসম্মত নয়, যদিও এটি x86 যা করে। (এবং যে এটি significand যে বনাম sNaN qNaN নির্ধারণ করে এর MSB এর হয় আদর্শায়িত)। en.wikedia.org/wiki/Single- precision_floating- point_ formt বলছে x86 এবং এআরএম একই, তবে পিএ-আরআইএসসি বিপরীত পছন্দটি করেছে।
পিটার কর্ডেস

@ পিটারকর্ডস হ্যাঁ, আমি নিশ্চিত নই যে আইইইই 754 20at এ "উচিত" == "অবশ্যই" বা "পছন্দনীয়" কি হবে "একটি সিগন্যালিং এনএইন বিট স্ট্রিংটি পিছনের তাত্পর্যপূর্ণ ক্ষেত্রের প্রথম বিট 0 এবং" এর সাথে এনকোড করা উচিত।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件 法轮功

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

২০০৮ এর আগে, আইইইই 75৫৪ বলেছিল যা কোনটি সিগন্যালিং / স্লিপ বিট (বিট 22) তবে কোন মানটি নির্দিষ্ট করে তা নয়। বেশিরভাগ প্রসেসর 1 = নিঃশব্দে রূপান্তরিত হয়েছিল, তাই এটিকে ২০০৮ সংস্করণে স্ট্যান্ডার্ডের অংশ করা হয়েছিল। এটি বলেছে যে পুরানো বাস্তবায়নগুলি একই পছন্দটিকে অ-সঙ্গতিপূর্ণ করে তুলেছে তা এড়াতে "উচিত" পরিবর্তে "উচিত"। সাধারণভাবে, "মানক" মানে "অবশ্যই" আবশ্যক, যদি না আপনি না মেনে চলার কারণী খুব জোরালো (এবং ভালভাবে ডকুমেন্টেড) কারণগুলি পান "।
জন কাওয়ান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.