1.0 এর নিকটতম ডাবলটি কী, এটি 1.0 নয়?


89

প্রোগ্রামালমেটিকভাবে ডাবল পাওয়ার কোনও উপায় কি 1.0 এর নিকটতম, তবে আসলে 1.0 নয়?

এটি করার একটি হ্যাকি উপায় হ'ল ডাবলটিকে একই আকারের পূর্ণসংখ্যার সাথে স্মরণ করা এবং তার পরে একটিকে বিয়োগ করা। আইইইই 7575৫ ফ্লোটিং-পয়েন্ট ফর্ম্যাটগুলি যেভাবে কাজ করে, এটি সমস্ত জিরো (1.00000000000000) থেকে সমস্তকে (1.11111111111111) ভগ্নাংশের অংশ পরিবর্তন করার সময় একের সাথে এক্সপোঞ্জারটিকে হ্রাস পাবে। তবে এমন মেশিন রয়েছে যেখানে পূর্ণসংখ্যাগুলি স্বল্প-এডিয়ান সংরক্ষণ করা হয় যখন ভাসমান-পয়েন্টটি বড়-এন্ডিয়ান সংরক্ষণ করা হয়, যাতে এটি সর্বদা কার্যকর হয় না।


4
আপনি ধরে নিতে পারবেন না যে +1 একই দূরত্ব (1.0 থেকে) -1 হিসাবে। বেস 10 এবং বেস 2 ভাসমান পয়েন্ট উপস্থাপনার ইন্টারলেভিংয়ের অর্থ ফাঁকগুলি অসম হয় ven
রিচার্ড ক্রিটেন

4
@ রিচার্ড: আপনি ঠিক বলেছেন। এটি খুব সম্ভব না যে একটি ইউএলপিকে বিয়োগ করার ফলে, এর, "পরবর্তী" মানটি পাওয়া যাবে, কারণ আমার ধারণা যে খাঁটিটিকেও সামঞ্জস্য করতে হবে। nextafter()তিনি যা চান তা অর্জনের একমাত্র সঠিক উপায়।
রুডি ভেলথুইস

4
এফওয়াইআইয়ের এই ব্লগটি আমার রয়েছে (আমার নয়): এক্সপ্লোরিংবাইনারি.
com/…

4
@ রুডিভেলথুইস: এটি প্রতিটি আইইইই 7575৫ বাইনারি ফ্লোটিং পয়েন্ট ফর্ম্যাটে কাজ করে।
এডগার বোনেট

4
ঠিক আছে, তাহলে আমাকে বলুন: "প্রতিটি আইইইই 754 ফ্লোটিং পয়েন্ট ফর্ম্যাটে কী কাজ করে"? এটি কেবল সত্য নয় যে আপনি যদি "ফার্স্টফেরোভার ()" মানটি অর্জন করেন তাত্পর্যটি হ্রাস করেন, বিশেষত 1.0 এর জন্য নয়, যার একটি তাত্পর্য রয়েছে যা দুটি শক্তি of এর অর্থ হ'ল 1.0000...বাইনারি হ্রাস 0.111111....এবং এটিকে স্বাভাবিক করার জন্য, আপনাকে অবশ্যই এটি বামে স্থানান্তরিত করতে হবে: 1.11111...যার জন্য আপনাকে ক্ষয়কারীকে হ্রাস করতে হবে। এবং তারপরে আপনি 1.0 থেকে 2 গজ দূরে। সুতরাং না, অবিচ্ছেদ্য মান থেকে একটিকে বিয়োগ করা আপনাকে এখানে যা জিজ্ঞাসা করা হয় তা দেয় না।
রুডি ভেলথুইস

উত্তর:


23

সি এবং সি ++ এ, নিম্নলিখিতটি 1.0 এর নিকটতম মান দেয়:

#include <limits.h>

double closest_to_1 = 1.0 - DBL_EPSILON/FLT_RADIX;

তবে নোট করুন যে C ++ এর পরবর্তী সংস্করণগুলিতে limits.hপক্ষে হ্রাস করা হয়েছে climits। তবে, আপনি যদি যাইহোক সি ++ নির্দিষ্ট কোড ব্যবহার করেন তবে আপনি ব্যবহার করতে পারেন

#include <limits>

typedef std::numeric_limits<double> lim_dbl;
double closest_to_1 = 1.0 - lim_dbl::epsilon()/lim_dbl::radix;

এবং জারোড 42 যেমন তার উত্তরে লিখেছেন, যেহেতু C99 বা C ++ 11 আপনি এগুলি ব্যবহার করতে পারেন nextafter:

#include <math.h>

double closest_to_1 = nextafter(1.0, 0.0);

অবশ্যই সি ++ এ আপনি এর পরিবর্তে (এবং পরবর্তী সি ++ সংস্করণগুলির জন্য) অন্তর্ভুক্ত cmathএবং ব্যবহার করতে পারেন std::nextafter


144

যেহেতু সি ++ ১১, আপনি nextafterপ্রদত্ত দিকনির্দেশে পরবর্তী উপস্থাপনামূলক মান পেতে ব্যবহার করতে পারেন :

std::nextafter(1., 0.); // 0.99999999999999989
std::nextafter(1., 2.); // 1.0000000000000002

ডেমো


11
এটি পরবর্তী উপস্থাপনযোগ্য পূর্ণসংখ্যার দ্বিগুণ বাড়ানোর জন্য একটি দুর্দান্ত উপায় std::ceil(std::nextafter(1., std::numeric_limits<double>::max()))
জোহানেস স্কাউব -

44
পরের প্রশ্নটি হতে চলেছে "এটি কীভাবে স্টাডলিবায় প্রয়োগ করা হয়": পি
লাইটনেস রেস

18
@ লাইটনেসেসেসিনঅরবিতের মন্তব্য পড়ার পরে আমি কৌতূহল পেয়েছি। এভাবেই জন্য glibc কার্যকরী হয়nextafter , এবং এই কিভাবে musl কার্যকরী এটা অন্য ক্ষেত্রে যে কেউ দেখতে কিভাবে এটি সম্পন্ন চায়। মূলত: কাঁচা বিট টুইডলিং।
কর্নস্টালক

4
@ কর্নস্টালকস: আমি বিস্মিত হই না যে এটি কিছুটা কমে যাচ্ছে, অন্য একমাত্র বিকল্প সিপিইউ সমর্থন থাকবে।
ম্যাথিউ এম।

4
বিট টুইডলিং এটি সঠিকভাবে করার একমাত্র উপায়, আইএমও O আপনি ধীরে ধীরে এটির কাছে যাওয়ার চেষ্টা করে অনেক পরীক্ষার চেষ্টা করতে পারেন তবে এটি খুব ধীর হতে পারে।
রুডি ভেলথুইস

23

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

#include <float.h>
...
double value = 1.0+DBL_EPSILON;

DBL_EPSILON 1 এর মধ্যে পার্থক্যটি হ'ল 1 এর চেয়ে কম মানের প্রতিনিধিত্বযোগ্য।

আসল মানটি দেখতে আপনাকে এটিকে কয়েকটি অঙ্কে মুদ্রণ করতে হবে।

আমার প্ল্যাটফর্মে, printf("%.16lf",1.0+DBL_EPSILON)দেয় 1.0000000000000002


10
সুতরাং যে ডেমো1. হিসাবে অন্য কিছু মান জন্য কাজ করবে না1'000'000
Jarod42

7
@ জারোড 42: আপনি ঠিক বলেছেন, তবে ওপি বিশেষত সে সম্পর্কে জিজ্ঞাসা করে 1.0। বিটিডাব্লু, এটি 1 এর চেয়েও নিকটতম মান দেয় এবং 1 এর নিখুঁততম মানটি দেয় না (যা সম্ভবত 1 এর চেয়ে ছোট)। সুতরাং আমি একমত যে এটি একটি আংশিক উত্তর, তবে আমি ভেবেছিলাম এটি তবুও অবদান রাখতে পারে।
বারাক মনোস

@ লুভানহফ্যাক: আমি উত্তরের সীমাবদ্ধতা এবং অন্যদিকে নিকটতম সম্পর্কে যথাযথতা দিচ্ছি।
জারোড 42

7
এটি 1.0 এর নিকটতম ডাবল দেয় না , কারণ (বেস 2 ধরে) 1.0 এর আগে ডাবল ডানটি 1.0 এর পরে ডাবল ডানদিকে যতটা দূরে থাকে (যা আপনি গণনা করেন)।
celtschk

@ এসলেটস্ক্ক: আপনি ঠিক বলেছেন, আমি উপরের মন্তব্যে এটি ব্যাখ্যা করেছি
বারাক মনোস

4

সি ++ এ আপনি এটি ব্যবহার করতে পারেন

1 + std::numeric_limits<double>::epsilon()


4
@Zwol তেহনিকভাবে সাধারণত বাইনারি ভাসমান-পয়েন্ট বাস্তবায়নের জন্য এটি 1 এবং 2-অ্যাপসিলনের মধ্যে যে কোনও মানের জন্য কাজ করবে। তবে, হ্যাঁ, আপনি ঠিক বলেছেন যে এটি কেবলমাত্র 1 এ প্রয়োগ করার গ্যারান্টিযুক্ত
এলোমেলো 832

7
প্রযুক্তিগতভাবে এটি 1 এর জন্য কাজ করে না, যেহেতু 1 এর নিকটতম সংখ্যাটি 1 এর আগে সংখ্যাটি ঠিক, তার পরে একও নয়। ডবল 0.5 এবং 1 এর মধ্যে এর স্পষ্টতা, 1 এবং 2 এর মধ্যে তার স্পষ্টতা হিসাবে উচ্চ হিসাবে দুইবার 1 শেষ হওয়ার আগে অত: পর সংখ্যা ডান কাছাকাছি 1.
HelloGoodbye
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.