পাইথনের হ্যাশ অফ ইনফিনিটি কেন π এর অঙ্ক করে?


241

পাইথন মধ্যে ইনফিনিটির হ্যাশ সংখ্যা ম্যাচিং হয়েছে পাই :

>>> inf = float('inf')
>>> hash(inf)
314159
>>> int(math.pi*1e5)
314159

এটি কি কেবল কাকতালীয় বা ইচ্ছাকৃত?


9
নিশ্চিত নয়, তবে আমার ধারণা এটি hash(float('nan'))হ'ল যতটা ইচ্ছাকৃত 0
CS95

1
হুম, এ সম্পর্কে কোনও উল্লেখ নেই sys.hash_info। ইস্টার ডিম?
উইম

123
টিম পিটার্স জিজ্ঞাসা করুন। 19 বছর আগে তিনি এই ধ্রুবকটি চালু করেছিলেন এমন প্রতিশ্রুতি দেওয়া এখানে: github.com/python/cpython/commit/… । আমি যখন বিশেষ হ্যাশগুলি বাগ
মার্ক ডিকিনসন

8
@ মার্কডিকিনসন ধন্যবাদ দেখে মনে হচ্ছে টিম মূলত ইনফ এর হ্যাশের জন্য এর অঙ্কগুলি ব্যবহার করেছে ।
উইম

17
@ উইম আহ, হ্যাঁ, সত্য। এবং স্পষ্টতই আমি এটি পরিবর্তন করেছি -314159। আমি এটি সম্পর্কে ভুলে গিয়েছিলাম।
মার্ক ডিকিনসন

উত্তর:


47

_PyHASH_INFহয় একটি ধ্রুবক হিসেবে সংজ্ঞায়িত করা থেকে সমান 314159

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


6
ছোট nitpick: এটা যে একই মান, অন্যান্য হ্যাশ জন্য ব্যবহার করা হবে এই ক্ষেত্রে যেমন সংজ্ঞা দ্বারা প্রায় অনিবার্য hash(314159)হয় 314159। পাইথন 3, hash(2305843009214008110) == 314159(এই ইনপুটটি 314159 + sys.hash_info.modulus) ইত্যাদিতেও চেষ্টা করুন
শ্রীবতসার

3
@ শ্রীভাতসারআর আমার ঠিক অর্থ হ'ল যতক্ষণ তারা সংজ্ঞা অনুসারে এই মানটিকে অন্য মানগুলির হ্যাশ হিসাবে বেছে না নেয়, ততক্ষণ এই জাতীয় অর্থবহ মানটি বেছে নেওয়ার ফলে হ্যাশের সংঘর্ষের সম্ভাবনা বাড়বে না
প্যাট্রিক হাহ

220

সংক্ষিপ্তসার: এটি কোনও কাকতালীয় ঘটনা নয়; পাইথনের ডিফল্ট _PyHASH_INFসিপথন বাস্তবায়নে হার্ডকোডটি 314159 হিসাবে রয়েছে এবং 2000 সালে টিম পিটার্স কর্তৃক নির্বিচার মান হিসাবে (স্পষ্টত π এর অঙ্কগুলি থেকে) বেছে নেওয়া হয়েছিল


মান hash(float('inf'))সাংখ্যিক ধরনের জন্য বিল্ট ইন হ্যাশ ফাংশন সিস্টেম নির্ভর পরামিতি এক, এবং পাওয়া যায় যেমন sys.hash_info.infপাইথন 3:

>>> import sys
>>> sys.hash_info
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003, algorithm='siphash24', hash_bits=64, seed_bits=128, cutoff=0)
>>> sys.hash_info.inf
314159

( পাইপাইয়ের সাথেও একই ফলাফল ))


কোডের ক্ষেত্রে, hashএকটি অন্তর্নির্মিত ফাংশন। একটি পাইথন ভাসা বস্তুর উপর এটি কলিং ফাংশন যার পয়েন্টার দেওয়া হয় এমন কিছুকে ডাকে, tp_hashঅ্যাট্রিবিউট বিল্ট-ইন ভাসা প্রকার (এর PyTypeObject PyFloat_Type), যা হয়float_hash ফাংশন, সংজ্ঞায়িত হিসাবে return _Py_HashDouble(v->ob_fval), যেটা ঘুরে ফিরে গেছে

    if (Py_IS_INFINITY(v))
        return v > 0 ? _PyHASH_INF : -_PyHASH_INF;

যেখানে _PyHASH_INFহয় হিসাবে সংজ্ঞায়িত 314159:

#define _PyHASH_INF 314159

ইতিহাসের নিরিখে প্রথম উল্লেখ 314159পাইথন কোডে এই প্রেক্ষাপটে (আপনি এই সঙ্গে জানতে পারেন git bisectবা git log -S 314159 -p) দ্বারা যোগ করা হয়েছিল টিম পিটার্স এখন কমিট হয় আগস্ট 2000 সালে, 39dce293 মধ্যে cpythonGit সংগ্রহস্থলের।

প্রতিশ্রুতিবদ্ধ বার্তা বলেছেন:

Http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 এর জন্য ঠিক করুন । এটি একটি বিভ্রান্তিমূলক বাগ ছিল - সত্য "বাগ" হ'ল অসীম hash(x)হলে ত্রুটি ফিরে পেয়েছিল x। স্থির। এতে নতুন Py_IS_INFINITYম্যাক্রো যুক্ত হয়েছে pyport.h। ট্রান্টের আগের ছুরিকাটিকে একটি যৌক্তিক উপসংহারে ঠেলে দিয়ে ভাসা এবং জটিল সংখ্যার হ্যাশিংয়ের ক্রমবর্ধমান সদৃশতা হ্রাস করার জন্য পুনরায় সাজানো কোড। স্থিরভাবে অত্যন্ত বিরল বাগ যেখানে ফ্লোটের হ্যাশিং -১ ফিরে আসতে পারে এমনকি যদি কোনও ত্রুটি না ঘটে (পরীক্ষার কেসটি নির্মাণের চেষ্টা করার সময় নষ্ট না করে, এটি ঘটতে পারে এমন কোড থেকে এটি পরিষ্কার ছিল )। জটিল হ্যাশ উন্নত হয়েছে যাতে hash(complex(x, y))পদ্ধতিগতভাবে hash(complex(y, x))আর সমান হয় না।

বিশেষ করে, এই কমিট তিনি কোডটি ripped static long float_hash(PyFloatObject *v)মধ্যে Objects/floatobject.cএবং এটা তৈরি return _Py_HashDouble(v->ob_fval);, এবং সংজ্ঞা long _Py_HashDouble(double v)মধ্যে Objects/object.cতিনি লাইন যোগ করেছেন:

        if (Py_IS_INFINITY(intpart))
            /* can't convert to long int -- arbitrary */
            v = v < 0 ? -271828.0 : 314159.0;

সুতরাং উল্লিখিত হিসাবে, এটি একটি স্বেচ্ছাসেবী পছন্দ ছিল। নোট করুন যে 271828 এর প্রথম কয়েকটি দশমিক সংখ্যা থেকে গঠিত ।

সম্পর্কিত পরে প্রতিশ্রুতিবদ্ধ:


44
ইনফ-এর জন্য -271828-এর পছন্দটি পাই সমিতিটি দুর্ঘটনাক্রমে ছিল যে কোনও সন্দেহ দূর করে।
রাসেল বোরোগোভ

24
@ রাসেলবোরোগোভ না তবে এটি প্রায় 10 মিলিয়ন গুণ কম সম্ভাব্য করে তোলে;)
পাইপ

8
@cmaster: উপরে অংশ কোথায় সেটা দেখুন মে 2010 বলছেন, উপর যথা ডকুমেন্টেশন অধ্যায় সাংখ্যিক ধরনের হ্যাশ এবং ইস্যু 8188 - ধারণা যে আমরা চাই hash(42.0)হিসাবে একই হতে hash(42), এছাড়াও হিসাবে একই hash(Decimal(42))এবং hash(complex(42))এবং hash(Fraction(42, 1))। সমাধান (মার্ক ডিকিনসন দ্বারা) একটি মার্জিত একটি আইএমও: কোনও গাণিতিক ফাংশন সংজ্ঞায়িত করে যা কোনও যুক্তিযুক্ত সংখ্যার জন্য কাজ করে এবং ভাসমান-পয়েন্ট সংখ্যাগুলিও যুক্তিযুক্ত সংখ্যা হিসাবে ব্যবহার করে।
শ্রীভাতসার

1
@ শ্রীভাতসার আর আহ, আপনাকে ধন্যবাদ যদিও আমি এই সমতার গ্যারান্টি দেবার যত্ন নেব না, তবে এটি জেনে রাখা ভাল যে আপাতদৃষ্টিতে জটিল
কোডটির

2
@cmaster পূর্ণসংখ্যার জন্য হ্যাশ ফাংশনটি কেবল hash(n) = n % Mএম = যেখানে (2 ^ 61 - 1)। hash(p/q) = (p/q) mod Mবিভাজনকে মডুলো এম (অন্য কথায় hash(p/q) = (p * inverse(q, M)) % M:) ব্যাখ্যা করার সাথে যুক্তিযুক্ত এটিকে সাধারণীকরণ করা হয় । যে কারণে আমরা এটি চাই: যদি কোনও ডিক্টের মধ্যে dরাখি d[x] = fooএবং তারপরে আমাদের x==y(উদাহরণস্বরূপ 42.0 == 42) থাকে তবে এটির d[y]মতো না হয় d[x], তবে আমাদের সমস্যা হবে। আপাতদৃষ্টিতে জটিল কোডটি ভাসমান-বিন্দু বিন্যাসের প্রকৃতি থেকেই আসে, ভগ্নাংশটি সঠিকভাবে পুনরুদ্ধার করতে এবং ইনফ এবং এনএএন মানগুলির জন্য বিশেষ-ক্ষেত্রেগুলির প্রয়োজন হয়।
শ্রীভাতসার

12

প্রকৃতপক্ষে,

sys.hash_info.inf

আয় 314159। মান উত্পন্ন হয় না, এটি উত্স কোডের মধ্যে অন্তর্নির্মিত। আসলে,

hash(float('-inf'))

-271828পাইথন 2 এ ফিরে আসে বা প্রায় -e ( এটি এখন -314159 )।

দুটি সর্বকালের সবচেয়ে বিখ্যাত দুটি অযৌক্তিক সংখ্যা হ্যাশ মান হিসাবে ব্যবহৃত হয় তা এটিকে কাকতালীয় হওয়ার সম্ভাবনা খুব কম করে দেয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.