সি ++ এ ডাবল (বা ভাসমান) NaN আছে কিনা তা পরীক্ষা করা হচ্ছে


368

কোন ইসানান () ফাংশন আছে?

PS: আমি MinGW এ আছি (যদি এটি কোনও পার্থক্য করে)।

আমি ইশানান () এর মাধ্যমে ব্যবহার করে এটি সমাধান করেছি <math.h>, যা বিদ্যমান নেই <cmath>, যা আমি #includeপ্রথমে ইঙ্গিত করছিলাম ।


2
আমি খাঁটি না আপনি এটি বহনযোগ্যভাবে করতে পারেন। কে বলছেন যে সি ++ এর জন্য আইইইই 754 প্রয়োজন?
ডেভিড হেফারনান 26'11


কেবল একটি নোট, 1 ওজ প্রতিরোধের নিরাময় 1 পাউন্ডের চেয়ে ভাল। অন্য কথায়, 0.f / 0.f কে কখনও মৃত্যুদন্ড কার্যকর করা থেকে বিরত রাখা আপনার কোডটিতে পূর্ববর্তী অবস্থানের জন্য যাচাই করার চেয়ে অনেক ভাল nannanএটি আপনার প্রোগ্রামের জন্য মারাত্মক ধ্বংসাত্মক হতে পারে, যদি প্রসারিত করার অনুমতি দেওয়া হয় তবে এটি বাগগুলি খুঁজে পাওয়া শক্তভাবে প্রবর্তন করতে পারে। এটি কারণ nanবিষাক্ত, (5 * nan= nan), nanকোনও কিছুর ( nan! = nan) সমান nanনয় , কোনও কিছুর ( nan!> 0) এর nanচেয়ে বড় নয় , কোনও কিছুর চেয়ে কম নয় ( nan! <0)।
বোবোবো

1
@ বোবোবো: এটি একটি বৈশিষ্ট্য যা কেন্দ্রিয় ত্রুটি যাচাইয়ের অনুমতি দেয়। রিটার্ন ভ্যালু বনাম যেমন ব্যতিক্রম।
বেন ভয়েগট

2
<cmath> ইসানান () নেই কেন? এটি
স্ট্যান্ডে

উত্তর:


349

আইইইই স্ট্যান্ডার্ড অনুসারে, এনএএন মানগুলির মধ্যে একটি বিচিত্র সম্পত্তি রয়েছে যা তাদের সাথে জড়িত তুলনাগুলি সর্বদা মিথ্যা। অর্থাত্, একটি ভাসমান চ এর জন্য, চ শুধুমাত্র এনএএন f != fহলেই সত্য হবে ।

নোট করুন, নীচে কিছু মন্তব্য উল্লেখ করেছে যে কোড সংশোধন করার সময় সমস্ত সংকলক এটি সম্মান করে না।

আইইইইই ফ্লোটিং পয়েন্ট ব্যবহার করার দাবি করে যে কোনও সংকলকের জন্য, এই কৌশলটি কাজ করা উচিত । কিন্তু আমি নিশ্চয়তা দিতে পারে না এটা হবে বাস্তবে কাজ করি। সন্দেহ হলে আপনার সংকলকটি পরীক্ষা করুন।


4
কোনও আইইইই মোডে চলতে থাকলে সংকলকটি এটিকে আরও ভাল করে সরিয়ে ফেলেনি। অবশ্যই আপনার
সংকলকটির

38
-1 কেবল তত্ত্বে কাজ করে, অনুশীলনে নয়: সংযোজক যেমন জি ++ (সাথে-রেস্তোঁরা সহ) স্ক্রু এটি। একমাত্র সাধারণ উপায়, সি ++ 0 এক্স অবধি বিটপ্যাটার্ন পরীক্ষা করা।
চিয়ার্স এবং এইচটিএইচ - আলফ

66
@ অ্যালাফ: -ffast-mathবিকল্পের জন্য ডকুমেন্টেশন স্পষ্টভাবে বলেছে যে এটি এমন প্রোগ্রামগুলির জন্য ভুল আউটপুট তৈরি করতে পারে যা আইইইই বা আইএসও বিধি / গণিতের ক্রিয়াকলাপগুলির জন্য নির্দিষ্টকরণের ক্ষেত্রে যদি সঠিক প্রয়োগের উপর নির্ভর করে। এই বিকল্পটি সক্ষম না করে, ব্যবহার x != xকরা NaN এর জন্য সঠিকভাবে বৈধ এবং পোর্টেবল উপায়।
অ্যাডাম রোজেনফিল্ড

7
@ অ্যাডাম: ডকুমেন্টেশনটি খোলামেলাভাবে জানায় যে এটি হ'ল না। এবং হ্যাঁ আমি গ্যাব্রিয়েল ডস রেসের সাথে দীর্ঘ সময় নিয়ে এ নিয়ে আলোচনা করার আগে এই যুক্তির মুখোমুখি হয়েছি। এটি সাধারণত একটি বিজ্ঞপ্তি যুক্তিতে নকশাটি রক্ষার জন্য ব্যবহৃত হয় (আমি জানি না যে আপনি এটির সাথে যুক্ত হতে চান কিনা, তবে এটি সম্পর্কে জানার পক্ষে মূল্য - এটি শিখা যুদ্ধের জিনিস)। আপনার সিদ্ধান্তটি যা x != xবৈধতা ছাড়াই বৈধ is এটি জি ++ এর একটি নির্দিষ্ট সংস্করণের জন্য সত্য হতে পারে, না। যাইহোক, আপনার কাছে গ্যারান্টি দেওয়ার কোনও উপায় নেই যে ফাস্টম্যাথ বিকল্পটি ব্যবহার করা হবে না।
চিয়ার্স এবং এইচটিএইচ - আলফ

7
@ আলফ: না আমি গ্যাব্রিয়েল ডস রেসের সাথে আপনার আলোচনার বিষয়ে অবগত ছিলাম না। স্টিভ জেসোপ আইইইইর প্রতিনিধিত্ব অনুমান করার বিষয়ে অন্যান্য প্রশ্নের একটি দুর্দান্ত বক্তব্য রেখেছিলেন। আপনি যদি ধরে নেন যে আইইইই 754 এবং কম্পাইলারটি মানানসই পদ্ধতিতে কাজ করছে (অর্থাত্ -ffast-mathবিকল্প ব্যতীত), তবে x != xএটি একটি বৈধ এবং বহনযোগ্য সমাধান। এমনকি আপনি ম্যাক্রোর -ffast-mathজন্য পরীক্ষা করেও পরীক্ষা করতে পারেন __FAST_MATH__এবং সেই ক্ষেত্রে আলাদা বাস্তবায়নে স্যুইচ করতে পারেন (যেমন ইউনিয়ন এবং বিট টুইডলিং ব্যবহার করুন)।
অ্যাডাম রোজেনফিল্ড 23

220

isnan()বর্তমান সি ++ স্ট্যান্ডার্ড লাইব্রেরিতে কোনও ফাংশন নেই । এটি C99 এ চালু হয়েছিল এবং ম্যাক্রো হিসাবে কোনও সংশ্লেষ হিসাবে সংজ্ঞায়িত হয়েছিল । সি 99 দ্বারা সংজ্ঞায়িত স্ট্যান্ডার্ড লাইব্রেরির উপাদানগুলি বর্তমান সি ++ স্ট্যান্ডার্ড আইএসও / আইসিসি 14882: 1998 এর কোনও অংশ নয় তবে এর আপডেটটি আইএসও / আইইসি 14882: 2003 নয়।

2005 সালে প্রযুক্তিগত প্রতিবেদন 1 প্রস্তাব করা হয়েছিল। টিআর 1 সি 99 এর সাথে সি ++ এর সাথে সামঞ্জস্যতা নিয়ে আসে। সত্ত্বেও এটি সরকারীভাবে কখনও সি ++ স্ট্যান্ডার্ড হওয়ার জন্য গৃহীত হয়নি, অনেকগুলি ( জিসিসি 4.0+ বা ভিজ্যুয়াল সি ++ 9.0+ সি ++ বাস্তবায়ন টিআর 1 বৈশিষ্ট্যগুলি সরবরাহ করে, সেগুলি বা কেবলমাত্র কিছু (ভিজ্যুয়াল সি ++ 9.0 সি 99 গণিতের ক্রিয়াকলাপ সরবরাহ করে না)) ।

তাহলে TR1 পাওয়া যায়, তারপর cmathমত C99 উপাদান অন্তর্ভুক্ত isnan(), isfinite()ইত্যাদি কিন্তু তারা ফাংশন, না ম্যাক্রো, সাধারণত হিসেবে সংজ্ঞায়িত করা হয় std::tr1::, নামস্থান যদিও অনেক বাস্তবায়নের (অর্থাত জিসিসি 4+ লিনাক্স বা উপর XCode উপর Mac OS X এর 10.5+) তাদের উদ্বুদ্ধ সরাসরি std::, তাই std::isnanভাল সংজ্ঞায়িত করা হয়।

তদুপরি, সি ++ এর কিছু বাস্তবায়ন সি ++ এর জন্য C99 isnan()ম্যাক্রো উপলব্ধ করে (এর মাধ্যমে অন্তর্ভুক্ত cmathবা এর মাধ্যমে math.h), যা আরও বিভ্রান্তি সৃষ্টি করতে পারে এবং বিকাশকারীরা এটি স্ট্যান্ডার্ড আচরণ বলে ধরে নিতে পারে।

Viusal সি সম্পর্কে একটি নোট ++ উপরের হিসাবে উল্লেখ করা হয়েছে, এটা উপলব্ধ করা হয় না std::isnanতন্ন তন্ন std::tr1::isnan, কিন্তু এটা একটি এক্সটেনশন ফাংশন হিসাবে সংজ্ঞায়িত প্রদান করে _isnan()যা থেকে উপলব্ধ করা হয়েছে ভিসুয়াল সি ++ 6.0

এক্সকোডে আরও মজা আছে। উল্লিখিত হিসাবে, জিসিসি 4+ সংজ্ঞায়িত করে std::isnan। সংকলক এবং লাইব্রেরি ফর্ম এক্সকোডের পুরানো সংস্করণগুলির জন্য, এটি (এখানে প্রাসঙ্গিক আলোচনা হয় ) মনে হয়, নিজেকে পরীক্ষা করার সুযোগ পাননি) দুটি ফাংশন সংজ্ঞায়িত করা হয়েছে, __inline_isnand()ইনটেল এবং __isnand()পাওয়ার পিসিতে।


21
ইসন ন্যান বা আইস ইনফিনিটির মতো এই ফাংশনগুলি সবাই চায়। দায়িত্বে থাকা লোকেরা কেন কেবল তাদের মানগুলিতে অন্তর্ভুক্ত হয় না ???? - আমি কীভাবে দায়িত্বে নেব এবং এটির জন্য আমার ভোটটি কীভাবে রাখব তা জানার চেষ্টা করব। সিরিয়াসলি।
শুহালো

8
@ শুহালো ইনচার্জ এখনও?
টোমা জ্যাটো - মনিকা

11
এই উত্তরটি আপডেট করা উচিত যেহেতু std::isnanএখন সি ++ 11 মানের অংশ এবং সমর্থনটি প্রসারিত হয়েছে। এসটিডি :: isnan ভিসুয়াল স্টুডিও বাস্তবায়িত হয়েছিল ভিসুয়াল স্টুডিও 2013 হয়তো @shuhalo ভারপ্রাপ্ত :-) পেয়েছিলাম দিয়ে শুরু
aberaud

170

প্রথম সমাধান: আপনি যদি সি ++ 11 ব্যবহার করেন

যেহেতু এটি জিজ্ঞাসা করা হয়েছিল সেখানে কিছুটা নতুন উন্নয়ন হয়েছে: এটি জেনে রাখা গুরুত্বপূর্ণ যে std::isnan()এটি C ++ 11 এর অংশ

সংক্ষিপ্তসার

শিরোনামে সংজ্ঞায়িত <cmath>

bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)

প্রদত্ত ভাসমান পয়েন্ট সংখ্যাটি আরগটি একটি-সংখ্যা ( NaN) নয় কিনা তা নির্ধারণ করে ।

পরামিতি

arg: ভাসমান পয়েন্ট মান

ফেরত মূল্য

trueযদি আরগ হয় NaN, falseঅন্যথায়

উল্লেখ

http://en.cppreference.com/w/cpp/numeric/math/isnan

অনুগ্রহ করে নোট করুন যে এটি জি -++ ব্যবহার করে-রেস্তোঁরা-গণিতের সাথে বেমানান, অন্যান্য পরামর্শের জন্য নীচে দেখুন।


অন্যান্য সমাধান: আপনি যদি নন সি ++ 11 অনুবর্তী সরঞ্জাম ব্যবহার করেন

C99 এর জন্য, সি-তে, এটি ম্যাক্রো হিসাবে প্রয়োগ করা হয় isnan(c)যা কোনও মান মান দেয়। প্রকারটি xভাসমান, দ্বৈত বা দীর্ঘ ডাবল হতে হবে।

বিভিন্ন বিক্রেতারা একটি ফাংশন অন্তর্ভুক্ত বা নাও করতে পারেন isnan()

পরীক্ষা করার জন্য কল্পনানুসারে পোর্টেবল পথ NaNআইইইই 754 সম্পত্তি যে ব্যবহার করা NaNনিজেই সমান নয়: অর্থাত x == xজন্য মিথ্যা হতে হবে xহচ্ছে NaN

তবে সর্বশেষ বিকল্পটি প্রতিটি সংকলক এবং কিছু সেটিংস (বিশেষত অপ্টিমাইজেশন সেটিংস) এর সাথে কাজ না করে, তাই শেষ অবলম্বনে আপনি সর্বদা বিট প্যাটার্নটি পরীক্ষা করতে পারেন ...


8
অবশ্যই গ্রহণযোগ্য উত্তর হওয়ার যোগ্য এবং আরও বেশি অগ্রাধিকারের দাবিদার।
টিপটির

3
-1 std::isnan এখনও ফেব্রুয়ারী 2017 হিসাবে একটি ungood সুপারিশ যেহেতু এটি ছ ++, এর ফ্লোটিং পয়েন্ট অপ্টিমাইজেশান সাথে কাজ করে না হয়।
চিয়ার্স এবং এইচটিএইচ - Alf

@ চিয়ারসান্থথ.-আলফ: এই বিকল্পটি আইইইই অনুগত? উত্তরটি সম্পাদনা করা হয়েছে
ব্লুট্রিন

@BlueTrin: উভয় x != xএবং isnanআইইইই 754 মেনে চলার জন্য কাজ করার প্রয়োজন হয়। দ্বিতীয়টির বিষয়ে, আইইইই 754-2008 স্ট্যান্ডার্ডে বলা হয়েছে যে "বাস্তবায়নগুলি সমস্ত সমর্থিত পাটিগণিত ফর্ম্যাটগুলির জন্য নিম্নলিখিত অ-গণনামূলক ক্রিয়াকলাপ সরবরাহ করবে" এবং "ইসএনএএনএন (এক্স) সত্য এবং যদি কেবল এক্স এনএএন হয় তবে"। মানকটির প্রয়োজনীয়তা is754version1985()এবং এটির is754version2008()পরিবর্তে যেখানে সি ++ প্রদান করা হয় তা পরীক্ষা করার জন্য std::numeric_limits<Fp>::is_iec559()(আইইসি 559 একই মানের)। দুর্ভাগ্যক্রমে -ffast-mathঅপ্টিমাইজেশানের সাথে, যেমন g ++ দাবি হিসাবে দাবি করে তবে এটি মেনে চলা যায় না।
চিয়ার্স এবং এইচটিএইচ - Alf

1
সতর্কতা: ইসানান (এক্স) কেবলমাত্র সিসি এবং ঝনঝনিতে -ফিন্টেমেট-ম্যাথ-বিকল্পের সাথে কাজ করে না
একটি কুয়াশা

82

বুস্টে একটি শিরোলেখ-কেবল লাইব্রেরি রয়েছে যাতে ভাসমান পয়েন্ট ডাটাটাইপগুলি মোকাবেলা করার জন্য ঝরঝরে সরঞ্জাম রয়েছে

#include <boost/math/special_functions/fpclassify.hpp>

আপনি নিম্নলিখিত ফাংশন পেতে:

template <class T> bool isfinite(T z);
template <class T> bool isinf(T t);
template <class T> bool isnan(T t);
template <class T> bool isnormal(T t);

আপনার যদি সময় থাকে তবে বুস্টের কাছ থেকে পুরো ম্যাথ টুলকিটটি দেখুন, এর অনেক দরকারী সরঞ্জাম রয়েছে এবং দ্রুত বাড়ছে।

এছাড়াও ভাসমান এবং অ-ভাসমান পয়েন্টগুলির সাথে কাজ করার সময় সংখ্যাগত রূপান্তরগুলি লক্ষ্য করা ভাল ধারণা হতে পারে ।


1
ধন্যবাদ! শুধু আমি যা খুঁজছিলাম।
ডাঃ ওয়াটসন

এটি বুস্ট ১.৩৩-এ যুক্ত হয়েছে (আমি সবেমাত্র পেয়েছি যে আমার প্রোগ্রামটি পুরানো লিনাক্স ডিস্ট্রোতে সংকলন করে না)।
মার্সিন

2
আপনি যদি বিকল্প - গণিত বিকল্পটি সংকলন করেন তবে এই ফাংশনটি প্রত্যাশার মতো কাজ করবে না।
গায়েতানো মেন্ডোলা

43

তিনটি "অফিসিয়াল" উপায় রয়েছে: পিক্সিক্স isnanম্যাক্রো , সি ++ 0 এক্স isnanফাংশন টেম্পলেট বা ভিজ্যুয়াল সি ++ _isnanফাংশন

দুর্ভাগ্যক্রমে এটি ব্যবহার করতে হবে তা সনাক্ত করা বরং বরং ব্যবহারিক।

এবং দুর্ভাগ্যক্রমে, আপনার NAN এর সাথে আইইইই 754 উপস্থাপনা আছে কিনা তা সনাক্ত করার কোনও নির্ভরযোগ্য উপায় নেই। স্ট্যান্ডার্ড লাইব্রেরিটি এমনভাবে অফিসিয়াল অফার দেয় (numeric_limits<double>::is_iec559 ) সরবরাহ করে। তবে অনুশীলন সংকলকগুলিতে যেমন জি ++ স্ক্রু।

তত্ত্বের ক্ষেত্রে কেউ সাধারণভাবে ব্যবহার করতে পারে x != xতবে জি ++ এবং ভিজ্যুয়াল সি ++ এর মতো সংকলকগুলি এটি আপ করতে পারে।

সুতরাং শেষ পর্যন্ত, নির্দিষ্ট এনএএন বিটপ্যাটার্নগুলির জন্য পরীক্ষা করে ধরে নিন (এবং আশাকরি প্রয়োগ করা হচ্ছে, কোনও সময়ে!) আইইইইই 754 এর মতো একটি নির্দিষ্ট উপস্থাপনা।


সম্পাদনা করুন : "জি ++ এর মতো সংকলক ... স্ক্রু যে আপ" এর উদাহরণ হিসাবে বিবেচনা করুন

#include <limits>
#include <assert.h>

void foo( double a, double b )
{
    assert( a != b );
}

int main()
{
    typedef std::numeric_limits<double> Info;
    double const nan1 = Info::quiet_NaN();
    double const nan2 = Info::quiet_NaN();
    foo( nan1, nan2 );
}

জি ++ (টিডিএম -2 মিংডাব্লু 32) 4.4.1 সহ সংকলন:

সি: \ পরীক্ষা> টাইপ করুন "সি: \ প্রোগ্রাম ফাইলগুলি com @ কম্যান্ডস \ gnuc.bat"
@ রেম-ফিনপুট-চরসেট = উইন্ডোজ-1252
@ g ++ -O -pedantic -std = c ++ 98 -Wall -Wwrit-string% * -নো-দীর্ঘ-দীর্ঘ

সি: \ পরীক্ষা> গুনুক x.cpp

সি: \ পরীক্ষা> এ && এর প্রতিধ্বনি কাজ করে ... || প্রতিধ্বনি! ব্যর্থ
কাজ ...

সি: \ পরীক্ষা> জিনুক x.cpp - প্রথা - গণিত

সি: \ পরীক্ষা> এ && এর প্রতিধ্বনি কাজ করে ... || প্রতিধ্বনি! ব্যর্থ
দৃ failed়তা ব্যর্থ হয়েছে: ক! = বি, ফাইল x.cpp, লাইন 6

এই অ্যাপ্লিকেশনটি রানটাইমটিকে অস্বাভাবিক উপায়ে বন্ধ করার জন্য অনুরোধ করেছে।
আরও তথ্যের জন্য দয়া করে অ্যাপ্লিকেশনটির সহায়তা দলের সাথে যোগাযোগ করুন।
!ব্যর্থ হয়েছে

সি: \ পরীক্ষা> _

4
@ অ্যালাফ: আপনার উদাহরণটি ম্যাক ওএস এক্স এবং লিনাক্স উভয় ক্ষেত্রে জি ++ এর বিভিন্ন সংস্করণে 4.0 এবং 4.5 এর মধ্যে প্রত্যাশার মতো কাজ করে। -ffast-mathবিকল্পের জন্য ডকুমেন্টেশন স্পষ্টভাবে বলেছে যে এটি প্রোগ্রামগুলির জন্য ভুল আউটপুট তৈরি করতে পারে যা আইইইই বা আইএসও বিধি / গণিতের ক্রিয়াকলাপগুলির জন্য নির্দিষ্টকরণের ক্ষেত্রে যদি সঠিক প্রয়োগের উপর নির্ভর করে। এই বিকল্পটি সক্ষম না করে, ব্যবহার x != xকরা NaN এর জন্য সঠিকভাবে বৈধ এবং পোর্টেবল উপায়।
অ্যাডাম রোজেনফিল্ড

6
@ অ্যাডাম: আপনি যা মিস করছেন তা হ'ল সি ++ স্ট্যান্ডার্ডের জন্য ফ্লোটগুলির জন্য আইইইই প্রতিনিধিত্ব বা গণিতের প্রয়োজন হয় না। যতদুর man পৃষ্ঠা আপনাকে বলে, যেমন gcc -ffast-mathএখনও একটি অনুসারী সি ++ বাস্তবায়ন (অবশ্য এটি পায় অভিমানী numeric_limits::is_iec559ঠিক আছে, তা না হয়, যদিও আলফ উপরে এটা না যে প্রস্তাব দেওয়া): সি ++ আইইইই উপর নির্ভর কোড না পোর্টেবল সি ++ এবং কোন অধিকার নেই এটি সরবরাহ করতে বাস্তবায়ন আশা করা।
স্টিভ জেসোপ

5
এবং আলফের সঠিক, জিসিসি ৪.৩.৪-তে দ্রুত পরীক্ষা এবং is_iec559এটি সত্য -ffast-math। সুতরাং এখানে সমস্যাটি হ'ল জিসিসির ডকগুলি কেবলমাত্র এটিই বলেছে যে এটি -ffast-mathগণিতের ক্রিয়াকলাপগুলির জন্য নন-আইইইই / আইএসও, যদিও তাদের বলা উচিত এটি নন-সি ++, কারণ এটির বাস্তবায়ন numeric_limitsবিরক্ত। আমি অনুমান করব যে জিসিসি সর্বদা বলতে পারবেন না যে টেমপ্লেটটি সংজ্ঞায়িত করা হয়, ঘটনাটি ব্যাকএন্ডে আসলে অনুসারে চলমান আছে, এবং তাই চেষ্টাও করে না। আইআইআরসি-তে জিসিসির সি 99 এর কনফর্মেন্সের জন্য বকেয়া বাগ তালিকায় একই রকম সমস্যা রয়েছে।
স্টিভ জেসোপ

1
@ আলফ, @ স্টিভ, আমি জানতাম না সি ++ স্ট্যান্ডার্ডের ভাসমান-পয়েন্টের মানগুলির কোনও স্পেসিফিকেশন নেই। এটা আমার কাছে বেশ মর্মস্পর্শী। এটি স্ট্যান্ডার্ডের পরিবর্তে আইআইইই 754 এবং NaN প্ল্যাটফর্ম নির্দিষ্ট এক্সটেনশন হিসাবে পরিচালনা করা আরও ভাল দেখায়। তাই না? এবং আমি কি C ++ 0x এ যুক্ত হওয়া কোনও ধরণের ইসসান () বা আইইইই 754 আশা করতে পারি?
ইওনিল

3
@ ইউনিল: সি ++ 0 এক্স এর এখনও উদাহরণ রয়েছে "fl ওটিং-পয়েন্ট ধরণের মান উপস্থাপন হ'ল বাস্তবায়ন-ডি fi নেড"। সি এবং সি ++ উভয়ই লক্ষ্য রাখে যে কোনও ফ্লোটিং-পয়েন্ট হার্ডওয়্যারবিহীন মেশিনগুলিতে প্রয়োগগুলি সমর্থন করে এবং যথাযথ-সঠিক বিকল্পের চেয়ে যথাযথ আইইইই 754 ফ্লোটগুলি অনুকরণ করতে বেশ কিছুটা ধীর হতে পারে। তত্ত্বটি হ'ল আপনার is_iec559যদি আইইইই দরকার হয় তবে আপনি জোর করে বলতে পারেন, বাস্তবে এটি জিসিসিতে কাজ করে না। সি ++ 0 এক্স এর একটি isnanকার্যকারিতা রয়েছে, তবে যেহেতু is_iec559এখন জিসিসি সঠিকভাবে প্রয়োগ করে না , তাই আমি অনুমান করি এটি সি ++ 0x তেও আসবে না এবং এটি -ffast-mathসম্ভবত ভালভাবে ভেঙে যাবে isnan
স্টিভ জেসোপ

39

Std :: isnan আছে যদি আপনি সংকলক c99 এক্সটেনশানগুলি সমর্থন করেন তবে আমি নিশ্চিত নই যে মিংডাব্লু তা করবে কিনা।

এখানে একটি ছোট ফাংশন যা আপনার কম্পাইলারের মানক ফাংশন না থাকলে কাজ করা উচিত:

bool custom_isnan(double var)
{
    volatile double d = var;
    return d != d;
}

6
কেন শুধু ভার!
ব্রায়ান আর বন্ডি

8
যখন তাদের সুযোগটি হয় তখন কম্পাইলার তুলনাটি সর্বোত্তম করে তুলবে, সর্বদা সত্য ফিরে আসবে।
সিটিটি

23
না সেখানে নেই। একটি সংকলক এটি করে যা ভেঙে যায়। আপনি সম্ভবত এটিও বলতে পারেন যে স্ট্যান্ডার্ড লাইব্রেরিটি isnanভুল ফল দেয় বলে একটি সুযোগ আছে । প্রযুক্তিগতভাবে সত্য, সংকলকটি বাগিচা হতে পারে, তবে বাস্তবে এটি হবে না, ঘটবে। হিসাবে একই var != var। এটি কাজ করে কারণ আইইইই ভাসমান পয়েন্টের মানগুলি কীভাবে সংজ্ঞায়িত করা হয়।
জাল্ফ

29
যদি -পস্ট-ম্যাথ সেট করা থাকে তবে ইসনান () জিসিসির জন্য সঠিক ফলাফল দিতে ব্যর্থ হবে। অবশ্যই, এই অপ্টিমাইজেশানটি আইইইই শব্দার্থবিজ্ঞান ভঙ্গ হিসাবে নথিভুক্ত করা হয়েছে ...
ম্যাথু হার্মান

যদি -Fast-math সেট করা থাকে তবে কম্পাইলারটি বাগি হয়। বা পরিবর্তে, যদি -পাস্ত-গণিত সেট করা থাকে তবে সমস্ত বেট বন্ধ রয়েছে এবং আপনি যাইহোক এনএএনএস-এ নির্ভর করতে পারবেন না।
অ্যাড্রিয়ান রত্নপালা

25

পরীক্ষা করার জন্য আপনি স্ট্যান্ডার্ড লাইব্রেরিতে numeric_limits<float>::quiet_NaN( )সংজ্ঞায়িত ব্যবহার করতে পারেন limits। এর জন্য একটি পৃথক ধ্রুবক নির্দিষ্ট করা আছে double

#include <iostream>
#include <math.h>
#include <limits>

using namespace std;

int main( )
{
   cout << "The quiet NaN for type float is:  "
        << numeric_limits<float>::quiet_NaN( )
        << endl;

   float f_nan = numeric_limits<float>::quiet_NaN();

   if( isnan(f_nan) )
   {
       cout << "Float was Not a Number: " << f_nan << endl;
   }

   return 0;
}

আমি জানি না এটি সমস্ত প্ল্যাটফর্মে কাজ করে কিনা, যেমন আমি লিনাক্সে কেবল জি ++ দিয়ে পরীক্ষা করেছি।


2
সতর্কতা অবলম্বন করুন - জিসিসি সংস্করণ 3.2.3-তে সংখ্যাসূচক_ব্লিটগুলিতে একটি বাগ রয়েছে বলে মনে হচ্ছে, যেহেতু এটি শান্ত_নাএনের জন্য 0.0 প্রদান করে। জিসিসির পরবর্তী সংস্করণগুলি আমার অভিজ্ঞতাতে ঠিক আছে।
নাথান রান্নাঘর

@ নাথান: জেনে রাখা ভাল। আমি ৪.৩.২ সংস্করণটি ব্যবহার করছি, তাই আমি খুব ভালই জঙ্গলের বাইরে।
বিল

18

আপনি isnan()ফাংশনটি ব্যবহার করতে পারেন তবে আপনাকে সি গণিতের লাইব্রেরি অন্তর্ভুক্ত করতে হবে।

#include <cmath>

যেহেতু এই ফাংশনটি C99 এর অংশ, তাই এটি সর্বত্র পাওয়া যায় না। যদি আপনার বিক্রেতা ফাংশন সরবরাহ না করে তবে আপনি সামঞ্জস্যের জন্য নিজের বৈকল্পিকটিও সংজ্ঞায়িত করতে পারেন।

inline bool isnan(double x) {
    return x != x;
}

আমি <cmath> ব্যবহার করছিলাম এবং এতে কোন ইসানান নেই! প্রসঙ্গক্রমে আমি বুঝতে পারলাম যে হয় একটি isnanমধ্যে <math.h>
hasen

1
আমি যেমন বলেছি, এটি C99 এর অংশ। যেহেতু C99 কোনও বর্তমান সি ++ স্ট্যান্ডার্ডের অংশ নয়, আমি বিকল্পটি সরবরাহ করেছি। তবে ইসনান () আসন্ন সি ++ স্ট্যান্ডার্ডের অন্তর্ভুক্ত হওয়ার সম্ভাবনা রয়েছে বলে আমি এটির আশেপাশে একটি # স্বতন্ত্র নির্দেশনা রেখেছি।
raimue

12

নিম্নলিখিত কোডটি ন্যানের সংজ্ঞাটি ব্যবহার করেছে (সমস্ত এক্সপোশন বিটস সেট, কমপক্ষে একটি ভগ্নাংশ বিট সেট) এবং ধরে নিয়েছে যে আকার (ইনট) = সাইজফ (ফ্লোট) = 4 আপনি উইকিপিডিয়ায় এনএএন অনুসন্ধান করতে পারেন বিশদ সম্পর্কে।

bool IsNan( float value ) { return ((*(UINT*)&value) & 0x7fffffff) > 0x7f800000; }


আমি বিশ্বাস করি এটি বড় এন্ডিয়ান প্ল্যাটফর্মগুলিতেও কাজ করবে। আক্ষরিক 0x7fffffffকেবল মেমরি হিসাবে বসতে হবে ff ff ff 7fvalueএর মতো একই ক্রম রয়েছে 0x7f800000, তাই সমস্ত ক্রিয়াকলাপ শেষ হয় (কোনও বাইটের অদলবদল হয় না)। আমি আগ্রহী যদি কেউ এটি একটি বড় এন্ডিয়ান প্ল্যাটফর্মে পরীক্ষা করতে পারে।
ব্রায়ান ডাব্লু ওয়াগনার

0x7fff1234এটিও একটি এনএএন। তাই0xffffffff
স্টিভ হোল্যাশ

12

নান প্রতিরোধ

এই প্রশ্নের আমার উত্তরটি হ'ল বিপরীতমুখী চেকগুলি ব্যবহার না করাnan । ব্যবহার করুন প্রতিষেধক ফর্মের বিভাগের জন্য চেক 0.0/0.0পরিবর্তে।

#include <float.h>
float x=0.f ;             // I'm gonna divide by x!
if( !x )                  // Wait! Let me check if x is 0
  x = FLT_MIN ;           // oh, since x was 0, i'll just make it really small instead.
float y = 0.f / x ;       // whew, `nan` didn't appear.

nan অপারেশন থেকে ফলাফল 0.f/0.f , বা 0.0/0.0nanআপনার কোডটির স্থায়িত্বের জন্য একটি ভয়াবহ নেমেসিস যা আপনাকে খুব সতর্কতার সাথে সনাক্ত করতে হবে এবং প্রতিরোধ করতে হবে 1 । এর বৈশিষ্ট্যগুলি nanসাধারণ সংখ্যা থেকে পৃথক:

  • nanবিষাক্ত, (5 * nan= nan)
  • nanকোনও কিছুর সমান নয়, এমনকি নিজেরও নয় ( nan! = nan)
  • nanকোনও কিছুর চেয়ে বড় নয় ( nan!> 0)
  • nanকোনও কিছুর চেয়ে কম নয় ( nan! <0)

তালিকাভুক্ত সর্বশেষ 2 টি বৈশিষ্ট্যগুলি পাল্টা-যৌক্তিক এবং কোডের অদ্ভুত আচরণের ফলে কোনও nanসংখ্যার সাথে তুলনা করার উপর নির্ভর করবে (3 য় সর্বশেষ সম্পত্তিটিও বেশ আলাদা তবে আপনি সম্ভবত x != x ?আপনার কোডটি দেখতে যাচ্ছেন না ) যতক্ষণ না আপনি পরীক্ষা করছেন ন্যানের জন্য (অবিশ্বস্তভাবে))।

আমার নিজের কোডে, আমি লক্ষ্য করেছি যে nanমানগুলি বাগগুলি খুঁজে পেতে অসুবিধা তৈরি করে। (নোট করুন কীভাবে বা এর ক্ষেত্রে এটি নয় । ( <0) রিটার্ন দেয় , (0 < ) সত্য দেয় এবং এমনকি (inf-inf-infTRUEinf-inf < inf) সত্য প্রদান করে So সুতরাং, আমার অভিজ্ঞতায় কোডটির আচরণটি প্রায়শই এখনও পছন্দসই হিসাবে দেখা যায়)।

ননের অধীনে কি করতে হবে

আপনি কি অধীনে ঘটতে চান 0.0/0.0 অবশ্যই একটি বিশেষ কেস হিসাবে হ্যান্ডেল করা উচিত তবে অবশ্যই কোড থেকে বেরিয়ে আসা প্রত্যাশার উপর নির্ভরশীল।

উপরের উদাহরণে, ( 0.f/FLT_MIN) এর ফলাফলটি 0মূলত হবে। পরিবর্তে 0.0/0.0আপনি জেনারেট করতে পারেন HUGE। সুতরাং,

float x=0.f, y=0.f, z;
if( !x && !y )    // 0.f/0.f case
  z = FLT_MAX ;   // biggest float possible
else
  z = y/x ;       // regular division.

সুতরাং উপরের অংশে, যদি x থাকে 0.f,inf উপরেরগুলিতে ফলাফল আসবে (যা আসলে উপরে উল্লিখিত হিসাবে বেশ ভাল / ননডাস্ট্রেক্টিভ আচরণ রয়েছে)।

মনে রাখবেন, 0 দ্বারা পূর্ণসংখ্যা বিভাগ রানটাইম ব্যতিক্রম ঘটায় । সুতরাং আপনার অবশ্যই সর্বদা 0 দ্বারা পূর্ণসংখ্যা বিভাগের জন্য যাচাই করা উচিত কেবলমাত্র 0.0/0.0নিঃশব্দে মূল্যায়নের nanঅর্থ এই নয় যে আপনি অলস হতে পারেন এবং 0.0/0.0এটি হওয়ার আগে পরীক্ষা না করে ।

1 এর মাধ্যমে চেকগুলি কখনও কখনও অবিশ্বাস্য হয় ( কিছু অনুকূলকরণ সংকলক যে আইইইই সম্মতি ভঙ্গ করে, বিশেষত যখন স্যুইচ সক্ষম করা থাকে তখন তা ছিন্ন করে )।nanx != xx != x-ffast-math


এই বিষয়টি চিহ্নিত করার জন্য ধন্যবাদ; এর মতো প্রোগ্রামিং অবশ্যই সমস্যাটির সাথে অবশ্যই সহায়তা করবে। তবে পরের বার, দয়া করে খুব বেশি করে পাঠ্য বিন্যাসের বৈশিষ্ট্যগুলিকে অপব্যবহার না করার চেষ্টা করুন। ফন্টের আকার, ওজন এবং স্টাইলের স্যুইচিং এটি পড়তে সত্যিই শক্ত করে তুলছে।
ম্যাগনাস

4
মনে রাখবেন যে 0.0 / 0.0 কেবলমাত্র অপারেশন নয় যা কোনও NaN এর ফলাফল হতে পারে। Negativeণাত্মক সংখ্যার বর্গমূল মূলত NaN দেয়। + ইনফিনিটির কোসাইন এনএএনকেও ফেরত দেয়। অপারেশন অ্যাকোস (এক্স) যেখানে এক্স সীমার মধ্যে নেই [0, পাই] NaN এর ফলাফলও পেতে পারে। সংক্ষেপে, এই সম্ভাব্য ঝুঁকিপূর্ণ অপারেশনগুলি কেবল 0.0 / 0.0 এ নয়, সেদিকে নজর দিতেও অতিরিক্ত সতর্কতা অবলম্বন করতে হবে।
বরিস ডালস্টেইন

বোরিসের সাথে পুরোপুরি একমত। আমার অভিজ্ঞতায়, এনএন কার্যত সর্বদা স্কয়ার্ট (-1.302e-53) এর মতো কিছু থেকে আসে, অর্থাত নিকট থেকে শূন্য মধ্যবর্তী গণনার ফলাফল নেতিবাচকতার জন্য পরীক্ষা না করে স্কয়ার্টে খাওয়ানো হচ্ছে।
hans_meine

1
"এনএএনএস প্রতিরোধ" এর অর্থ হল যে আপনাকে কেবল বিভাজন নয়, সমস্ত বুনিয়াদি গাণিতিক ক্রিয়াকলাপগুলিতে প্রবেশ করতে হবে। আপনাকে আরও অনেকের মধ্যে ∞ / ∞, 0 * ∞, ∞% x, x% 0, ∞ - ∞, 0 ^ 0, ∞ ^ 0 এর জন্য নজর রাখতে হবে। এই জাতীয় বুনিয়াদি গাণিতিক ক্রিয়াকলাপগুলির সাথে "প্রতিরোধমূলক" হওয়ার অর্থ হ'ল আপনি আপনার কার্য সম্পাদনকে সম্পূর্ণরূপে ট্যাঙ্ক করবেন (এবং সম্ভবত অতিরিক্ত ক্ষেত্রে আপনি ভাবেননি যা ভাবেননি)।
স্টিভ হোল্যাশ

11

সি ++ 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বিকল্পের সাথে ব্যর্থ হয়েছে । কেবল প্রত্যক্ষ বিটপ্যাটার্ন পরীক্ষা নির্ভরযোগ্যভাবে কাজ করে।


7
inline bool IsNan(float f)
{
    const uint32 u = *(uint32*)&f;
    return (u&0x7F800000) == 0x7F800000 && (u&0x7FFFFF);    // Both NaN and qNan.
}

inline bool IsNan(double d)
{
    const uint64 u = *(uint64*)&d;
    return (u&0x7FF0000000000000ULL) == 0x7FF0000000000000ULL && (u&0xFFFFFFFFFFFFFULL);
}

এটি যদি sizeof(int)4 হয় এবং sizeof(long long)8 হয় তবে এটি কাজ করে ।

রান সময়ের সময় এটি কেবল তুলনা হয়, castালাইতে কোনও সময় লাগে না। এটি কেবল সাম্যতা পরীক্ষা করতে তুলনা পতাকাগুলির কনফিগারেশন পরিবর্তন করে changes


এছাড়াও মনে রাখবেন, এটি আইইইই 754 উপস্থাপনার মধ্যে সীমাবদ্ধ।
চিয়ার্স এবং এইচটিএইচ - Alf

মনে রাখবেন যে এই castালাইটি জি ++ এর কঠোর অ্যালাইজিং নিয়ম ভঙ্গ করে এবং সেই সংকলক আনমেনশনযোগ্য জিনিসগুলি করতে পরিচিত ™ যখন এটি আনুষ্ঠানিক ইউবি সনাক্ত করে। দক্ষ কাস্টের পরিবর্তে, g ++ সহ আপনার অবশ্যই memcpyবাইট অ্যারের মাধ্যমে নিশ্চিত হওয়া দরকার। আমার # 2 উত্তরে এর জন্য কোড
চিয়ার্স এবং এইচটিএইচ - Alf

4

ব্যবহৃত সম্ভাব্য সমাধান যা এনএএন-এর ব্যবহৃত নির্দিষ্ট আইইইই উপস্থাপনার উপর নির্ভর করবে না তা হ'ল:

template<class T>
bool isnan( T f ) {
    T _nan =  (T)0.0/(T)0.0;
    return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}

একক-নির্ভুলতা ভাসমান পয়েন্টে NaN এর জন্য 8 মিলিয়নেরও বেশি বৈধ এবং বিভিন্ন বিট নিন্দা রয়েছে, সুতরাং আপনাকে আরও কিছু তুলনা যুক্ত করতে হবে। :)
স্টিভ হোল্যাশ

4

বিবেচনা করে যে (x! = X) সবসময় NaN এর জন্য গ্যারান্টিযুক্ত নয় (যেমন যদি -Fast-math বিকল্পটি ব্যবহার করা হয়), আমি ব্যবহার করছি:

#define IS_NAN(x) (((x) < 0) == ((x) >= 0))

সংখ্যাগুলি <0 এবং> = 0 উভয়ই হতে পারে না, সুতরাং এই চেকটি কেবল তখনই পাস হয় যদি সংখ্যাটি কম বা শূন্যের চেয়ে বড় বা সমান না হয়। যা মূলত কোনও সংখ্যা বা নাএন নয়।

আপনি যদি এটি পছন্দ করেন তবে আপনি এটি ব্যবহার করতে পারেন:

#define IS_NAN(x) (!((x)<0) && !((x)>=0)

আমি নিশ্চিত না যদিও এটি কীভাবে চূড়ান্ত-গণিত দ্বারা প্রভাবিত হয়, তাই আপনার মাইলেজটি ভিন্ন হতে পারে।


এটি আসলে ত্রুটিযুক্ত একইভাবে f != fত্রুটিযুক্ত। আমি দেখতে পেয়েছি এলএলভিএম প্রায় এক অভিন্ন কোডের টুকরোটিকে অপ্টিমাইজ করে। অপ্টিমাইজারটি প্রথম তুলনা সম্পর্কে তথ্য প্রচার করতে পারে এবং নির্ধারণ করতে পারে যে দ্বিতীয় তুলনাটি যদি প্রথম হয় তবে কখনও সত্য হতে পারে না। (যদি সংকলক আইইইই বিধি কঠোরভাবে মান্য করেf != f কোনও উপায়ে সহজ)
মার্কাস

জি ++ এর -ffast-mathবিকল্পের সাথে কাজ করে না । ভিজ্যুয়াল সি ++ নিয়ে কাজ করে। ( স্ট্যাকওভারফ্লো . com / a / 42138465 / 464581 ) দেখুন।
চিয়ার্স এবং এইচটিএইচ - Alf

3

আমার পক্ষে সমাধানটি ম্যাক্রো হতে পারে এটি সুস্পষ্টভাবে ইনলাইন করতে এবং এইভাবে যথেষ্ট দ্রুত। এটি যে কোনও ফ্লোট টাইপের জন্যও কাজ করে। এটি এই ভিত্তিতে ভিত্তি করে যে মানটি যখন সমান হয় না তখনই কেবল তার মান হয় the

#ifndef isnan
  #define isnan(a) (a != a)
#endif

এটি এই প্রশ্নের সেরা উত্তর! ভাগ করার জন্য আপনাকে ধন্যবাদ।
হেনরি মেনকে

2
অন্যান্য উত্তরগুলি সূচিত করে যে এটি -স্টাস্ট-গণিত বিকল্প সেটটি সহ ব্যর্থ হতে পারে।
টেকনোফিল

3

এইটা কাজ করে:

#include <iostream>
#include <math.h>
using namespace std;

int main ()
{
  char ch='a';
  double val = nan(&ch);
  if(isnan(val))
     cout << "isnan" << endl;

  return 0;
}

আউটপুট: ইসানান


1

এটি আমার কাছে মনে হয় যে সত্যিকারের ক্রস-প্ল্যাটফর্ম পদ্ধতির একটি ইউনিয়ন ব্যবহার করা এবং NaNs পরীক্ষা করার জন্য ডাবলের বিট প্যাটার্নটি পরীক্ষা করা হবে।

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

#include <stdint.h>
#include <stdio.h>

union NaN
{
    uint64_t bits;
    double num;
};

int main()
{
    //Test if a double is NaN
    double d = 0.0 / 0.0;
    union NaN n;
    n.num = d;
    if((n.bits | 0x800FFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF)
    {
        printf("NaN: %f", d);
    }

    return 0;
}

নোট করুন যে "ইউনিয়নটির সদস্যের কাছ থেকে পড়া অবধারিত আচরণ যা সম্প্রতি লেখা হয়নি" " সুতরাং unionদুই প্রকারের মধ্যে টাইপ-পুনের এই ব্যবহারটি পছন্দসই হিসাবে কাজ করতে পারে না (: দু: খ_পাণ্ডা :))। সঠিক (যদিও পছন্দসই হিসাবে যথেষ্ট পোর্টেবল নয়) উপায়টি হ'ল ইউনিয়নটিকে পুরোপুরি এড়িয়ে চলতে হবে, এবং একটি মেমকি থেকে doubleআলাদা uint64_tভেরিয়েবলে পরিণত করা হবে, তারপরে সেই সহায়ক ভেরিয়েবলটি ব্যবহার করে পরীক্ষা করুন।
এলজয়

0

X86-64 এ আপনার কাছে NaN এবং অনন্তের জন্য চেক করার জন্য অত্যন্ত দ্রুত পদ্ধতি থাকতে পারে, যা -ffast-mathসংকলক বিকল্প নির্বিশেষে কাজ করে । ( f != f, std::isnan, std::isinfসবসময় উত্পাদ falseসঙ্গে -ffast-math)।


NaN, অনন্ত এবং সীমাবদ্ধ সংখ্যার জন্য পরীক্ষার জন্য সর্বাধিক ব্যয়কারীর জন্য পরীক্ষা করে সহজেই করা যেতে পারে। অনন্তটি শূন্য ম্যান্টিসার সাথে সর্বাধিক প্রকাশক, NaN সর্বাধিক ঘাতক এবং শূন্য নন ম্যান্টিসা। এক্সপোশনটি পরবর্তী বিটগুলিতে সর্বাধিক সাইন বিটের পরে সংরক্ষণ করা হয়, যাতে আমরা সাইন বিট থেকে মুক্তি পেতে এবং এক্সপোনেন্টটিকে শীর্ষতম বিটগুলি তৈরি করতে পারি, কোনও মাস্কিং operator&প্রয়োজন নেই:

static inline uint64_t load_ieee754_rep(double a) {
    uint64_t r;
    static_assert(sizeof r == sizeof a, "Unexpected sizes.");
    std::memcpy(&r, &a, sizeof a); // Generates movq instruction.
    return r;
}

static inline uint32_t load_ieee754_rep(float a) {
    uint32_t r;
    static_assert(sizeof r == sizeof a, "Unexpected sizes.");
    std::memcpy(&r, &a, sizeof a); // Generates movd instruction.
    return r;
}

constexpr uint64_t inf_double_shl1 = UINT64_C(0xffe0000000000000);
constexpr uint32_t inf_float_shl1 = UINT32_C(0xff000000);

// The shift left removes the sign bit. The exponent moves into the topmost bits,
// so that plain unsigned comparison is enough.
static inline bool isnan2(double a)    { return load_ieee754_rep(a) << 1  > inf_double_shl1; }
static inline bool isinf2(double a)    { return load_ieee754_rep(a) << 1 == inf_double_shl1; }
static inline bool isfinite2(double a) { return load_ieee754_rep(a) << 1  < inf_double_shl1; }
static inline bool isnan2(float a)     { return load_ieee754_rep(a) << 1  > inf_float_shl1; }
static inline bool isinf2(float a)     { return load_ieee754_rep(a) << 1 == inf_float_shl1; }
static inline bool isfinite2(float a)  { return load_ieee754_rep(a) << 1  < inf_float_shl1; }

stdএর সংস্করণ isinfএবং isfiniteলোড 2 double/floatথেকে ধ্রুবক .dataসেগমেন্ট এবং লক দৃশ্যকল্প তারা 2 ডেটা ক্যাসে শটটি সৃষ্টি করতে পারে। উপরের সংস্করণগুলিতে কোনও ডেটা লোড হয় না inf_double_shl1এবং inf_float_shl1অবিচ্ছিন্নভাবে নির্দেশাবলীর সাথে তাত্ক্ষণিক ক্রিয়াকলাপ হিসাবে ধ্রুবকগুলি এনকোড হয়ে যায়।


দ্রুত isnan2মাত্র 2 টি সমাবেশের নির্দেশাবলী:

bool isnan2(double a) {
    bool r;
    asm(".intel_syntax noprefix"
        "\n\t ucomisd %1, %1"
        "\n\t setp %b0"
        "\n\t .att_syntax prefix"
        : "=g" (r)
        : "x" (a)
        : "cc"
        );
    return r;
}

ucomisdকোনও যুক্তি যদি NaN হয় তবে নির্দেশটি সমতা পতাকা নির্ধারণ করে fact std::isnanকোনও -ffast-mathবিকল্প নির্দিষ্ট করা না হলে এইভাবে কাজ করে ।


-1

আইইইই স্ট্যান্ডার্ডটি বলে যে যখন 1ঘেরটি সমস্ত হয় এবং মান্টিসেটা শূন্য হয় না তখন সংখ্যাটি a হয় NaN। ডাবল হ'ল 1সাইন বিট, 11এক্সপোঞ্জার বিট এবং 52ম্যান্টিসার বিট। একটু চেক করুন।


-3

উপরে উল্লিখিত মন্তব্য হিসাবে a! = A g ++ এবং কিছু অন্যান্য সংকলকগুলিতে কাজ করবে না, তবে এই কৌশলটি হওয়া উচিত। এটি এতটা দক্ষ নাও হতে পারে তবে এটি এখনও একটি উপায়:

bool IsNan(float a)
{
    char s[4];
    sprintf(s, "%.3f", a);
    if (s[0]=='n') return true;
    else return false;
}

মূলত, g ++ এ (যদিও আমি অন্যের বিষয়ে নিশ্চিত নই) প্রিন্টফ% d বা% .f ফর্ম্যাটে 'নান' প্রিন্ট করে যদি ভেরিয়েবল বৈধ পূর্ণসংখ্যা / ভাসা না হয়। সুতরাং এই কোডটি স্ট্রিংয়ের প্রথম অক্ষরটি 'এন' হওয়ার জন্য পরীক্ষা করছে ("নান" হিসাবে)


2
এর ফলে যদি কোনও = 234324.0f হয় তবে বাফার উপচে পড়বে না?
মাজিওদ

হ্যাঁ, না, বা 340282346638528859811704183484516925440.000যদি = FLT_MAX। তাকে ব্যবহার করতে হবে char s[7]; sprintf(s, "%.0g", a);, যা 6 জন হবে যদি a=-FLT_MAXবা-3e+38
বোবোবো

-3

এটি অনন্তর সনাক্ত করে এবং ভিজ্যুয়াল স্টুডিওতে NAN এটি পরীক্ষা করে দ্বিগুণ সীমাতে রয়েছে:

//#include <float.h>
double x, y = -1.1; x = sqrt(y);
if (x >= DBL_MIN && x <= DBL_MAX )
    cout << "DETECTOR-2 of errors FAILS" << endl;
else
    cout << "DETECTOR-2 of errors OK" << endl;

সংজ্ঞা চেক করুন FLT_MIN, DBL_MINএবং LDBL_MINআরো সাবধানে। এগুলি প্রতিটি ধরণের জন্য সর্বনিম্ন সাধারণ মানের মান হিসাবে সংজ্ঞায়িত করা হয় । উদাহরণস্বরূপ, একক-নির্ভুলতার 8 মিলিয়নেরও বেশি বৈধ ডেনোম মান রয়েছে যা শূন্যের চেয়ে বেশি এবং কম FLT_MIN(এবং এনএএন নয়)।
স্টিভ হোল্যাশ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.