পাইথনে এলোমেলো সংখ্যার চূড়ান্ত অঙ্কগুলির বিতরণ


24

পাইথনে 0 থেকে 9 অবধি এলোমেলো অঙ্ক উত্পন্ন করার দুটি সুস্পষ্ট উপায় রয়েছে। একটি 0 এবং 1 এর মধ্যে একটি এলোমেলো ভাসমান পয়েন্ট সংখ্যা উত্পন্ন করতে পারে, 10 দ্বারা গুণিত এবং নীচে বৃত্তাকারে। বিকল্পভাবে, একটি random.randintপদ্ধতি ব্যবহার করতে পারে ।

import random

def random_digit_1():
    return int(10 * random.random())

def random_digit_2():
    return random.randint(0, 9)

আমি কৌতূহল ছিলাম যে যদি কেউ 0 থেকে 1 এর মধ্যে একটি এলোমেলো সংখ্যা তৈরি করে এবং শেষ সংখ্যাটি রাখে তবে কি হবে । অগত্যা বিতরণটি অভিন্ন হওয়ার আশা করিনি, তবে ফলাফলটি বেশ অবাক করেছিলাম।

from random import random, seed
from collections import Counter

seed(0)
counts = Counter(int(str(random())[-1]) for _ in range(1_000_000))
print(counts)

আউটপুট:

Counter({1: 84206,
         5: 130245,
         3: 119433,
         6: 129835,
         8: 101488,
         2: 100861,
         9: 84796,
         4: 129088,
         7: 120048})

নীচে একটি হিস্টোগ্রাম দেখানো হয়েছে। নোট করুন যে 0 টি প্রদর্শিত হবে না, যেহেতু অনুসরণীয় শূন্যগুলি কেটে গেছে। তবে কেউ কি ব্যাখ্যা করতে পারেন যে 4, 5 এবং 6 সংখ্যাগুলি কেন বাকীগুলির চেয়ে বেশি সাধারণ? আমি পাইথন 3.6.10 ব্যবহার করেছি তবে ফলাফল পাইথন 3.8.0a4 তে একই ছিল in

এলোমেলো ফ্লোটের চূড়ান্ত অঙ্কগুলির বিতরণ


4
পাইথনে যেভাবে ফ্লোটগুলির স্ট্রিং উপস্থাপনা গণনা করা হয় তার সাথে এটি করতে হবে। দেখুন docs.python.org/3/tutorial/floatingpoint.html । আপনি যদি দশকের অঙ্কটি (দশমিকের পরে প্রথম) ব্যবহার না করেন তবে আপনি আরও বেশি ফলাফল পেতে চাইবেন।
ডেনিস

1
আমরা বাইনারি উপস্থাপনে ভাসমান রাখি (যেহেতু আমাদের স্মৃতিশক্তিটিও বাইনারি হয়)। strএটিকে বেস -10 এ রূপান্তর করে যা সমস্যার কারণ হতে বাধ্য। উদাহরণস্বরূপ একটি 1-বিট ফ্লোট ম্যান্টিসা b0 -> 1.0এবং b1 -> 1.5। "শেষ সংখ্যা" সর্বদা 0বা হবে 5
মতিন উলহাক

1
random.randrange(10)আইএমএইচও, আরও সুস্পষ্ট। random.randint(যা random.randrangeহুডের নীচে কল করে) হ'ল randomপাইথনের ব্যাপ্তিগুলি কীভাবে কাজ করে তা বোঝে না এমন লোকদের মডিউলের পরে সংযোজন । ;)
সন্ধ্যা 2 টা রিং

2
@ পিএম 2 রিং: ইন্টারফেসটি ভুল randrangeহওয়ার পরে তারা দ্বিতীয় স্থানে এসেছিল randint
ব্যবহারকারী 2357112

@ ব্যবহারকারী 2357112 সমর্থন মনিকা ওহ, ঠিক আছে। আমি সংশোধন করেছি. আমি নিশ্চিত যে রেন্ডার্জ ১ ম হয়েছিল, তবে আমার স্মৃতি আগের মতো ভাল নয়। ;)
সন্ধ্যা 2 টা রিং

উত্তর:


21

এটি সংখ্যার "শেষ সংখ্যা" নয়। যে শেষ অঙ্ক এর স্ট্রিং strআপনার দেওয়া যখন সংখ্যা গৃহীত।

আপনি যখন strকোনও ফ্লোটে কল করবেন তখন পাইথন আপনাকে পর্যাপ্ত পরিমাণে অঙ্ক দেয় যে floatস্ট্রিংয়ে ফোন করা আপনাকে আসল ভাসা দেয়। এই উদ্দেশ্যে, 1 বা 9 এর পিছনে পিছনে যাওয়া অন্যান্য সংখ্যার তুলনায় কম হওয়ার সম্ভাবনা কম, কারণ 1 বা 9 অনুমানের অর্থ সংখ্যাটি সেই অঙ্কটির কাছাকাছি যা আপনি পেয়ে যাবেন to অন্য কোনও ফ্লোটের কাছাকাছি হওয়ার খুব ভাল সুযোগ রয়েছে এবং যদি তাই হয় তবে float(str(original_float))আচরণটিকে ত্যাগ ছাড়াই সেই সংখ্যাটি ফেলে দেওয়া যেতে পারে ।

strআর্গুমেন্টকে হুবহু উপস্থাপনের জন্য যদি আপনাকে পর্যাপ্ত অঙ্ক দেয়, তবে শেষ সংখ্যাটি সর্বদা সর্বদা ৫ হয়, random.random()0.0 এর পরিবর্তে, যখন শেষ সংখ্যাটি 0 হয় except কেবলমাত্র ফ্লোটগুলি ডায়াডিক যুক্তিগুলি উপস্থাপন করতে পারে এবং শেষ নজারিরো দশমিক অঙ্ক একটি অ-পূর্ণসংখ্যক ডায়াডিক যুক্তি সর্বদা 5)) ফলাফলগুলি দেখতে অত্যন্ত দীর্ঘ হবে looking

>>> import decimal, random
>>> print(decimal.Decimal(random.random()))
0.29711195452007921335990658917580731213092803955078125

এটি একটি কারণ যা strনা করে।

যদি strআপনাকে হুবুহু 17 টি উল্লেখযোগ্য অঙ্ক দেয় (সমস্ত ভাসমান মান একে অপরের থেকে আলাদা করার জন্য যথেষ্ট, তবে কখনও কখনও প্রয়োজনের চেয়ে আরও বেশি অঙ্ক) তবে আপনি যে প্রভাবটি দেখছেন তা অদৃশ্য হয়ে যাবে। পিছনে অঙ্কের প্রায় সমান বিতরণ হবে (0 সহ)

(এছাড়াও, আপনি ভুলে গেছেন যে strকখনও কখনও বৈজ্ঞানিক স্বরলিপি একটি স্ট্রিং ফিরে আসে, কিন্তু এটি একটি সামান্য প্রভাব, কারণ যে ভাসমান যেখানে সেখানে ঘটবে কম সম্ভাবনা আছে random.random()।)


5

টিএল; ডিআর আপনার উদাহরণটি আসলে শেষ সংখ্যাটির দিকে তাকিয়ে নেই। বেস -10 এ রূপান্তরিত একটি সসীম বাইনারি-উপস্থাপিত মান্টিসার শেষ অঙ্কটি সর্বদা হওয়া উচিত 0বা 5


একবার দেখুন cpython/floatobject.c:

static PyObject *
float_repr(PyFloatObject *v)
{
    PyObject *result;
    char *buf;

    buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
                                'r', 0,
                                Py_DTSF_ADD_DOT_0,
                                NULL);

    // ...
}

এবং এখন এ cpython/pystrtod.c:

char * PyOS_double_to_string(double val,
                                         char format_code,
                                         int precision,
                                         int flags,
                                         int *type)
{
    char format[32];
    Py_ssize_t bufsize;
    char *buf;
    int t, exp;
    int upper = 0;

    /* Validate format_code, and map upper and lower case */
    switch (format_code) {
    // ...
    case 'r':          /* repr format */
        /* Supplied precision is unused, must be 0. */
        if (precision != 0) {
            PyErr_BadInternalCall();
            return NULL;
        }
        /* The repr() precision (17 significant decimal digits) is the
           minimal number that is guaranteed to have enough precision
           so that if the number is read back in the exact same binary
           value is recreated.  This is true for IEEE floating point
           by design, and also happens to work for all other modern
           hardware. */
        precision = 17;
        format_code = 'g';
        break;
    // ...
}

উইকিপিডিয়া এটি নিশ্চিত করে:

53-বিট তাত্পর্যপূর্ণ নির্ভুলতা 15 থেকে 17 উল্লেখযোগ্য দশমিক অঙ্কের যথার্থতা দেয় (2 -53 ≈ 1.11 × 10 -16 )। সর্বাধিক ১৫ টি উল্লেখযোগ্য অঙ্কের দশমিক স্ট্রিং যদি আইইইই 754 ডাবল-স্পষ্টতা উপস্থাপনায় রূপান্তরিত হয় এবং একই সংখ্যার অঙ্কের সাথে দশমিক স্ট্রিংয়ে ফিরে রূপান্তরিত হয় তবে চূড়ান্ত ফলাফলটি মূল স্ট্রিংয়ের সাথে মেলে। যদি কোনও আইইইই 754 ডাবল-স্পষ্টতা নম্বরটি কমপক্ষে 17 টি উল্লেখযোগ্য অঙ্কের সাথে দশমিক স্ট্রিংয়ে রূপান্তরিত হয় এবং তারপরে ডাবল-স্পষ্টতা উপস্থাপনায় ফিরে রূপান্তরিত হয় তবে চূড়ান্ত ফলাফলটি অবশ্যই মূল সংখ্যার সাথে মেলে।

সুতরাং, যখন আমরা ব্যবহার করি str(বা repr), আমরা কেবল বেস -10 এ 17 টি উল্লেখযোগ্য অঙ্ক উপস্থাপন করি। এর অর্থ কিছু ভাসমান পয়েন্ট নম্বর কেটে যাবে। আসলে, সঠিক প্রতিনিধিত্ব পেতে আপনার 53 টি উল্লেখযোগ্য অঙ্কের নির্ভুলতা প্রয়োজন! আপনি নিম্নলিখিত হিসাবে এটি যাচাই করতে পারেন:

>>> counts = Counter(
...     len(f"{random():.99f}".lstrip("0.").rstrip("0"))
...     for _ in range(1000000)
... )
>>> counts
Counter({53: 449833,
         52: 270000,
         51: 139796,
         50: 70341,
         49: 35030,
         48: 17507,
         47: 8610,
         46: 4405,
         45: 2231,
         44: 1120,
         43: 583,
         42: 272,
         41: 155,
         40: 60,
         39: 25,
         38: 13,
         37: 6,
         36: 5,
         35: 4,
         34: 3,
         32: 1})
>>> max(counts)
53

এখন সর্বাধিক নির্ভুলতা ব্যবহার করে, "শেষ সংখ্যা" সন্ধানের সঠিক উপায়টি এখানে:

>>> counts = Counter(
...     int(f"{random():.53f}".lstrip("0.").rstrip("0")[-1])
...     for _ in range(1000000)
... )
>>> counts
Counter({5: 1000000})

দ্রষ্টব্য: ব্যবহারকারী 2357112 দ্বারা নির্দেশিত অনুসারে, সঠিকভাবে বাস্তবায়নগুলি দেখতে হবে PyOS_double_to_stringএবং format_float_shortতবে আমি বর্তমানগুলিকে ছেড়ে দেব কারণ তারা শিক্ষাগতভাবে আরও আকর্ষণীয়।


"সুতরাং, যখন আমরা str (বা repr) ব্যবহার করি, তখন আমরা কেবল বেস -10 এ 17 টি উল্লেখযোগ্য অঙ্ক উপস্থাপন করি।" - 17 সর্বোচ্চ। যদি এটি প্রকৃতপক্ষে একটি নির্দিষ্ট 17 ডিজিট হয় তবে প্রশ্নের প্রভাবটি উপস্থিত হবে না। প্রশ্নের প্রভাব কেবলমাত্র পর্যায়ে-অঙ্কগুলি থেকে রাউন্ড-ট্রিপ রাউন্ডিং str(some_float)ব্যবহারগুলি থেকে আসে।
ব্যবহারকারী 2357112

1
আপনি এর ভুল বাস্তবায়ন খুঁজছেন PyOS_double_to_string। যে বাস্তবায়ন পক্ষে আউট preprocessed হয় এই এক
user2357112 মনিকা সমর্থন

প্রথম মন্তব্য প্রসঙ্গে: হিসাবে উল্লেখ করেছে, একটি ফ্লোটিং পয়েন্ট সংখ্যা (সম্পাদনা: 0 একজন এক্সপোনেন্ট সঙ্গে) সঠিক উপস্থাপনা, 53 এতগুলি অর্থপূর্ণ অঙ্ক প্রয়োজন যদিও 17 গ্যারান্টি যথেষ্ট float(str(x)) == x। বেশিরভাগ ক্ষেত্রে, এই উত্তরটি প্রশ্নের মধ্যে থাকা অনুমানটি ("সঠিক উপস্থাপনার শেষ সংখ্যা") দেখানোর জন্যই ভুল ছিল, কারণ সঠিক ফলাফলটি কেবলমাত্র 5(এবং একটি সম্ভাবনা 0) নয়।
মতিন উলহাক

53 টি উল্লেখযোগ্য দশমিক সংখ্যা যথেষ্ট নয়। এখানে আরও একটি উদাহরণ রয়েছে।
ব্যবহারকারী 2357112

@ ব্যবহারকারী 2357112 সাপোর্টমোনিকা দুঃখিত, আমি 0 এর ব্যয়কারীকে বোঝাতে চাইছি (যা অন্তর [0, 1] এর মধ্যে অভিন্নতার গ্যারান্টি দেওয়ার জন্য প্রয়োজনীয়))
মতিন উলহাক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.