সি ++ 14 হিসাবে ভাসমান পয়েন্ট সংখ্যাটি পরীক্ষা করার বিভিন্ন উপায় রয়েছে value
কোনও এনএন ।
এই উপায়গুলির মধ্যে, কেবলমাত্র সংখ্যাটির উপস্থাপনের বিটগুলি পরীক্ষা করা , নির্ভরযোগ্যভাবে কাজ করে, যেমনটি আমার মূল উত্তরে উল্লিখিত হয়েছে। বিশেষত std::isnan
এবং প্রায়শই প্রস্তাবিত চেকv != v
নির্ভরযোগ্যতার সাথে কাজ করে না এবং ব্যবহার করা উচিত নয়, যাতে কেউ আপনার স্থিতিস্থাপক অপ্টিমাইজেশান প্রয়োজন বলে সিদ্ধান্ত নিলে সঠিকভাবে কাজ করা বন্ধ করে দেয় এবং সংস্থাপককে এটি করতে বলে that এই পরিস্থিতি বদলে যেতে পারে, সংকলকরা আরও মেনে চলতে পারে তবে মূল উত্তর থেকে 6 বছরের মধ্যে এই সমস্যাটি ঘটেনি।
প্রায় 6 বছর ধরে আমার আসল উত্তরটি এই প্রশ্নের নির্বাচিত সমাধান ছিল, যা ঠিক ছিল। তবে সম্প্রতি অবিশ্বাস্য v != v
পরীক্ষার সুপারিশকারী একটি উচ্চতর উত্তোলিত উত্তর নির্বাচন করা হয়েছে। সুতরাং এই অতিরিক্ত আরও আপ-টু-ডেট উত্তর (আমাদের এখন দিগন্তে সি ++ 11 এবং সি ++ 14 মান, এবং সি ++ 17 রয়েছে)।
সি ++ 14 অনুযায়ী NaN-ness চেক করার প্রধান উপায়গুলি হ'ল:
std::isnan(value) )
সি ++ 11 থেকে অভিযুক্ত স্ট্যান্ডার্ড লাইব্রেরি পথ। isnan
দৃশ্যত একই নামের পক্সিক্স ম্যাক্রোর সাথে দ্বন্দ্ব রয়েছে, তবে বাস্তবে এটি কোনও সমস্যা নয়। মূল সমস্যাটি হ'ল যখন ভাসমান পয়েন্ট গণিতের অপ্টিমাইজেশনের জন্য অনুরোধ করা হয়, তারপরে কমপক্ষে একটি মূল সংকলক, জি ++ নামক সাথে এনএন আর্গুমেন্টের জন্য std::isnan
ফিরে আসেfalse
।
(fpclassify(value) == FP_NAN) )
একই সমস্যা যেমন ভোগেন ততটা std::isnan
নির্ভরযোগ্য নয় from
(value != value) )
অনেক এসও উত্তরে প্রস্তাবিত। একই সমস্যা থেকে ভোগেনstd::isnan
নির্ভরযোগ্য নয়
(value == Fp_info::quiet_NaN()) )
এটি এমন একটি পরীক্ষা যা স্ট্যান্ডার্ড আচরণের সাথে NaNs সনাক্ত করা উচিত নয়, তবে এটি অনুকূলিত আচরণের সাহায্যে NaNs সনাক্ত করতে পারে (কেবলমাত্র বিটলভেল উপস্থাপনাগুলির সাথে সরাসরি তুলনা করার জন্য অনুকূলিত কোডের কারণে), এবং সম্ভবত স্ট্যান্ডার্ড আন-অপ্টিমাইজড আচরণকে আচ্ছাদন করার জন্য অন্য কোনও উপায়ের সাথে মিলিত হতে পারে , নির্ভরযোগ্যভাবে NaN সনাক্ত করতে পারে। দুর্ভাগ্যক্রমে এটি নির্ভরযোগ্যভাবে কাজ না করে।
(ilogb(value) == FP_ILOGBNAN) )
একই সমস্যা থেকে ভোগেন std::isnan
নির্ভরযোগ্য নয়
isunordered(1.2345, value) )
একই সমস্যা থেকে ভোগেন std::isnan
নির্ভরযোগ্য নয়
is_ieee754_nan( value ) )
এটি কোনও স্ট্যান্ডার্ড ফাংশন নয়। এটি আইইইই 754 মান অনুযায়ী বিটগুলি পরীক্ষা করছে। এটি সম্পূর্ণ নির্ভরযোগ্য তবে কোডটি কিছুটা সিস্টেম-নির্ভর-
নিম্নলিখিত সম্পূর্ণ পরীক্ষার কোডটিতে "সাফল্য" কোনও অভিব্যক্তিটি মূল্যের ন্যান-নেসকে রিপোর্ট করে কিনা। সাফল্যের এই পরিমাপের বেশিরভাগ অভিব্যক্তির জন্য, NaNs এবং কেবল NaNs সনাক্ত করার লক্ষ্যটি তাদের মানক শব্দার্থের সাথে মিলে যায়। জন্য(value == Fp_info::quiet_NaN()) )
অভিব্যক্তি অবশ্য মান আচরণ যে এটি একটি Nan-আবিষ্কারক হিসেবে কাজ করেন না।
#include <cmath> // std::isnan, std::fpclassify
#include <iostream>
#include <iomanip> // std::setw
#include <limits>
#include <limits.h> // CHAR_BIT
#include <sstream>
#include <stdint.h> // uint64_t
using namespace std;
#define TEST( x, expr, expected ) \
[&](){ \
const auto value = x; \
const bool result = expr; \
ostringstream stream; \
stream << boolalpha << #x " = " << x << ", (" #expr ") = " << result; \
cout \
<< setw( 60 ) << stream.str() << " " \
<< (result == expected? "Success" : "FAILED") \
<< endl; \
}()
#define TEST_ALL_VARIABLES( expression ) \
TEST( v, expression, true ); \
TEST( u, expression, false ); \
TEST( w, expression, false )
using Fp_info = numeric_limits<double>;
inline auto is_ieee754_nan( double const x )
-> bool
{
static constexpr bool is_claimed_ieee754 = Fp_info::is_iec559;
static constexpr int n_bits_per_byte = CHAR_BIT;
using Byte = unsigned char;
static_assert( is_claimed_ieee754, "!" );
static_assert( n_bits_per_byte == 8, "!" );
static_assert( sizeof( x ) == sizeof( uint64_t ), "!" );
#ifdef _MSC_VER
uint64_t const bits = reinterpret_cast<uint64_t const&>( x );
#else
Byte bytes[sizeof(x)];
memcpy( bytes, &x, sizeof( x ) );
uint64_t int_value;
memcpy( &int_value, bytes, sizeof( x ) );
uint64_t const& bits = int_value;
#endif
static constexpr uint64_t sign_mask = 0x8000000000000000;
static constexpr uint64_t exp_mask = 0x7FF0000000000000;
static constexpr uint64_t mantissa_mask = 0x000FFFFFFFFFFFFF;
(void) sign_mask;
return (bits & exp_mask) == exp_mask and (bits & mantissa_mask) != 0;
}
auto main()
-> int
{
double const v = Fp_info::quiet_NaN();
double const u = 3.14;
double const w = Fp_info::infinity();
cout << boolalpha << left;
cout << "Compiler claims IEEE 754 = " << Fp_info::is_iec559 << endl;
cout << endl;;
TEST_ALL_VARIABLES( std::isnan(value) ); cout << endl;
TEST_ALL_VARIABLES( (fpclassify(value) == FP_NAN) ); cout << endl;
TEST_ALL_VARIABLES( (value != value) ); cout << endl;
TEST_ALL_VARIABLES( (value == Fp_info::quiet_NaN()) ); cout << endl;
TEST_ALL_VARIABLES( (ilogb(value) == FP_ILOGBNAN) ); cout << endl;
TEST_ALL_VARIABLES( isunordered(1.2345, value) ); cout << endl;
TEST_ALL_VARIABLES( is_ieee754_nan( value ) );
}
জি ++ সহ ফলাফল (আবার নোট করুন যে এর স্ট্যান্ডার্ড আচরণটি (value == Fp_info::quiet_NaN())
হ'ল এটি একটি এনএএন-ডিটেক্টর হিসাবে কাজ করে না, এটি এখানে ব্যবহারিক আগ্রহের খুব বেশি):
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> জি ++ - রূপান্তর | "++" সন্ধান করুন
g ++ (x86_64-win32-sjlj-rev1, MinGW-W64 প্রকল্প দ্বারা নির্মিত) 6.3.0
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> g ++ foo.cpp && এ
সংকলক আইইইই 754 = সত্য দাবি করে
v = nan, (std :: isnan (value)) = সত্য সাফল্য
u = 3.14, (std :: isnan (মান)) = মিথ্যা সাফল্য
w = inf, (std :: isnan (মান)) = মিথ্যা সাফল্য
v = nan, ((fpclassify (মান) == 0x0100)) = সত্য সাফল্য
u = 3.14, ((fpclassify (মান) == 0x0100)) = মিথ্যা সাফল্য
w = inf, ((fpclassify (মান) == 0x0100)) = মিথ্যা সাফল্য
v = nan, ((মান! = মান)) = সত্য সাফল্য
u = 3.14, ((মান! = মান)) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((মান! = মান)) = মিথ্যা সাফল্য
v = নান, ((মান == এফপি_ইনফো :: নিঃশব্দ_নানা ())) = মিথ্যা ব্যর্থ
u = 3.14, ((মান == Fp_info :: शांत_নাএ ())) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((মান == এফপি_ইনফো :: শান্ত_নাআন ())) = মিথ্যা সাফল্য
v = নান, ((ইলোগব (মান) == ((প্রাক্তন) 0x80000000))) = সত্য সাফল্য
u = 3.14, ((ilogb (মান) == ((প্রাক্তন) 0x80000000))) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((আইলগবি (মান) == ((প্রাক্তন) 0x80000000))) = মিথ্যা সাফল্য
v = nan, (isunordered (1.2345, মান)) = সত্য সাফল্য
u = 3.14, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
w = inf, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
v = nan, (is_ieee754_nan (মান)) = সত্য সাফল্য
u = 3.14, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
w = inf, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> g ++ foo.cpp - দ্রুত-গণিত ও& ক
সংকলক আইইইই 754 = সত্য দাবি করে
v = nan, (std :: isnan (মান)) = মিথ্যা FAILED
u = 3.14, (std :: isnan (মান)) = মিথ্যা সাফল্য
w = inf, (std :: isnan (মান)) = মিথ্যা সাফল্য
v = nan, ((fpclassify (মান) == 0x0100)) = মিথ্যা FAILED
u = 3.14, ((fpclassify (মান) == 0x0100)) = মিথ্যা সাফল্য
w = inf, ((fpclassify (মান) == 0x0100)) = মিথ্যা সাফল্য
v = nan, ((মান! = মান)) = মিথ্যা ব্যর্থ
u = 3.14, ((মান! = মান)) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((মান! = মান)) = মিথ্যা সাফল্য
v = nan, ((মান == Fp_info :: शांत_নাএ ())) = সত্য সাফল্য
u = 3.14, ((মান == এফপি_ইনফো :: নিঃশব্দ_না) ()) = সত্য ব্যর্থ
ডাব্লু = ইনফ, ((মান == এফপি_ইনফো :: শান্ত_নাআন ())) = সত্য ব্যর্থ
v = নান, ((ইলোগব (মান) == ((প্রাক্তন) 0x80000000))) = সত্য সাফল্য
u = 3.14, ((ilogb (মান) == ((প্রাক্তন) 0x80000000))) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((আইলগবি (মান) == ((প্রাক্তন) 0x80000000))) = মিথ্যা সাফল্য
v = nan, (isunordered (1.2345, মান)) = মিথ্যা ব্যর্থ
u = 3.14, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
w = inf, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
v = nan, (is_ieee754_nan (মান)) = সত্য সাফল্য
u = 3.14, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
w = inf, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> _
ভিজ্যুয়াল সি ++ সহ ফলাফল:
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> cl / nologo- 2> & 1 | "++" সন্ধান করুন
মাইক্রোসফ্ট (আর) সি / সি ++ এক্স 86 এর জন্য সংকলক সংস্করণ 19.00.23725 অনুকূলকরণ করুন
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> সিএল foo.cpp / ফেব্রুয়ারী && খ
foo.cpp
সংকলক আইইইই 754 = সত্য দাবি করে
v = nan, (std :: isnan (value)) = সত্য সাফল্য
u = 3.14, (std :: isnan (মান)) = মিথ্যা সাফল্য
w = inf, (std :: isnan (মান)) = মিথ্যা সাফল্য
v = nan, ((fpclassify (মান) == 2)) = সত্য সাফল্য
u = 3.14, ((fpclassify (মান) == 2)) = মিথ্যা সাফল্য
w = inf, ((fpclassify (মান) == 2)) = মিথ্যা সাফল্য
v = nan, ((মান! = মান)) = সত্য সাফল্য
u = 3.14, ((মান! = মান)) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((মান! = মান)) = মিথ্যা সাফল্য
v = নান, ((মান == এফপি_ইনফো :: নিঃশব্দ_নানা ())) = মিথ্যা ব্যর্থ
u = 3.14, ((মান == Fp_info :: शांत_নাএ ())) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((মান == এফপি_ইনফো :: শান্ত_নাআন ())) = মিথ্যা সাফল্য
v = nan, ((ilogb (মান) == 0x7fffffff)) = সত্য সাফল্য
u = 3.14, ((ilogb (মান) == 0x7fffffff)) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((আইলগবি (মান) == 0x7fffffff)) = সত্য ব্যর্থ
v = nan, (isunordered (1.2345, মান)) = সত্য সাফল্য
u = 3.14, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
w = inf, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
v = nan, (is_ieee754_nan (মান)) = সত্য সাফল্য
u = 3.14, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
w = inf, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> সিএল foo.cpp / ফেব্রুয়ারী / এফপি: দ্রুত && বি
foo.cpp
সংকলক আইইইই 754 = সত্য দাবি করে
v = nan, (std :: isnan (value)) = সত্য সাফল্য
u = 3.14, (std :: isnan (মান)) = মিথ্যা সাফল্য
w = inf, (std :: isnan (মান)) = মিথ্যা সাফল্য
v = nan, ((fpclassify (মান) == 2)) = সত্য সাফল্য
u = 3.14, ((fpclassify (মান) == 2)) = মিথ্যা সাফল্য
w = inf, ((fpclassify (মান) == 2)) = মিথ্যা সাফল্য
v = nan, ((মান! = মান)) = সত্য সাফল্য
u = 3.14, ((মান! = মান)) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((মান! = মান)) = মিথ্যা সাফল্য
v = নান, ((মান == এফপি_ইনফো :: নিঃশব্দ_নানা ())) = মিথ্যা ব্যর্থ
u = 3.14, ((মান == Fp_info :: शांत_নাএ ())) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((মান == এফপি_ইনফো :: শান্ত_নাআন ())) = মিথ্যা সাফল্য
v = nan, ((ilogb (মান) == 0x7fffffff)) = সত্য সাফল্য
u = 3.14, ((ilogb (মান) == 0x7fffffff)) = মিথ্যা সাফল্য
ডাব্লু = ইনফ, ((আইলগবি (মান) == 0x7fffffff)) = সত্য ব্যর্থ
v = nan, (isunordered (1.2345, মান)) = সত্য সাফল্য
u = 3.14, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
w = inf, (isunordered (1.2345, মান)) = মিথ্যা সাফল্য
v = nan, (is_ieee754_nan (মান)) = সত্য সাফল্য
u = 3.14, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
w = inf, (is_ieee754_nan (মান)) = মিথ্যা সাফল্য
[সি: \ আমার \ ফোরাম \ তাই 2 282 (NaN সনাক্ত করুন)]
> _
উপরোক্ত ফলাফলগুলি সংক্ষেপ করে, কেবলমাত্র is_ieee754_nan
এই পরীক্ষার প্রোগ্রামে সংজ্ঞায়িত ফাংশনটি ব্যবহার করে বিট-লেভেল উপস্থাপনার সরাসরি পরীক্ষা- নিরীক্ষা, জি ++ এবং ভিজ্যুয়াল সি ++ উভয় ক্ষেত্রেই সমস্ত ক্ষেত্রে নির্ভরযোগ্যভাবে কাজ করেছে।
সংযোজন:
উপরের পোস্টের পরে আমি এনএএন পরীক্ষার জন্য আরও একটি সম্ভাব্য বিষয়ে সচেতন হয়েছি, এখানে অন্য উত্তরে উল্লিখিত , যথা ((value < 0) == (value >= 0))
। এটি ভিজ্যুয়াল সি ++ দিয়ে সূক্ষ্ম কাজ করতে দেখা গেছে তবে জি ++ এর -ffast-math
বিকল্পের সাথে ব্যর্থ হয়েছে । কেবল প্রত্যক্ষ বিটপ্যাটার্ন পরীক্ষা নির্ভরযোগ্যভাবে কাজ করে।