জাভা: 0 <= x <n ব্যাপ্তিতে এলোমেলো দীর্ঘ সংখ্যা


135

এলোমেলো শ্রেণীর একটি প্রদত্ত পরিসরে র্যান্ডম ইন্ট উত্পন্ন করার একটি পদ্ধতি রয়েছে। উদাহরণ স্বরূপ:

Random r = new Random(); 
int x = r.nextInt(100);

এটি আরও বা সমান 0 এবং 100 এর চেয়ে কম সংখ্যার উত্পন্ন সংখ্যা তৈরি করবে I'd আমি দীর্ঘ সংখ্যার সাথে ঠিক একই কাজ করতে চাই।

long y = magicRandomLongGenerator(100);

এলোমেলো ক্লাসে কেবল পরবর্তী লং () রয়েছে তবে এটি ব্যাপ্তি সেট করতে দেয় না।


সম্পর্কিত, দরকারী হতে পারে: stackoverflow.com/questions/2290057/…
টিজে ক্রাউডার

1
আপনি কি কেবলমাত্র আপনার দীর্ঘ এলোমেলো হওয়া এবং আপনার পরিসীমাটির মোড নেওয়ার বিষয়টি বিবেচনা করেছেন? (অবশ্যই, যদি পরিসীমাটি কেবলমাত্র 100 হয় তবে আমি একটি প্রাক এলোমেলো উত্পাদন করতে পারি এবং এটিকে দীর্ঘস্থায়ী করতে পারি))
হট লিকস

java.util.Randomকেবলমাত্র 48 বিট বিতরণ ব্যবহার করে (বাস্তবায়নের বিশদ দেখুন), সুতরাং এটির কোনও সাধারণ বিতরণ হবে না।
জেফ্রি ডি স্মেট

1
আধুনিক দিনগুলিতে org.apache.commons.lang3.RandomUtils # পরের দীর্ঘ ব্যবহার করা বিবেচনা করা যেতে পারে।
সত্যই চমৎকার

উত্তর:


149

থেকে শুরু করে জাভা 7 (অথবা অ্যান্ড্রয়েড এপিআই লেভেল 21 = 5.0+) আপনি সরাসরি ব্যবহার করতে পারে ThreadLocalRandom.current().nextLong(n)(0 জন্য ≤ এক্স <ঢ) এবং ThreadLocalRandom.current().nextLong(m, n)(ড জন্য ≤ এক্স <ঢ)। বিস্তারিত জানতে @ অ্যালেক্সের উত্তর দেখুন ।


আপনি যদি জাভা 6 (বা অ্যান্ড্রয়েড 4.x) এর সাথে আটকে থাকেন তবে আপনাকে একটি বাহ্যিক গ্রন্থাগার ব্যবহার করতে হবে (উদাহরণস্বরূপ org.apache.commons.math3.random.RandomDataGenerator.getRandomGenerator().nextLong(0, n-1), @ মওয়াল্ডেনের উত্তর দেখুন), বা আপনার নিজের প্রয়োগ করতে হবে nextLong(n)

Https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Random.html অনুসারে nextIntপ্রয়োগ করা হয়েছে

 public int nextInt(int n) {
     if (n<=0)
                throw new IllegalArgumentException("n must be positive");

     if ((n & -n) == n)  // i.e., n is a power of 2
         return (int)((n * (long)next(31)) >> 31);

     int bits, val;
     do {
         bits = next(31);
         val = bits % n;
     } while(bits - val + (n-1) < 0);
     return val;
 }

সুতরাং আমরা সম্পাদন করতে এটি পরিবর্তন করতে পারেন nextLong:

long nextLong(Random rng, long n) {
   // error checking and 2^x checking removed for simplicity.
   long bits, val;
   do {
      bits = (rng.nextLong() << 1) >>> 1;
      val = bits % n;
   } while (bits-val+(n-1) < 0L);
   return val;
}

1
"2 ^ x চেকিং" অংশটি নিয়ে আমার কিছু সমস্যা হচ্ছে। কোন ধারনা?
ভিলিয়াস নরম্যান্টাস

@ উইলিয়াস: 2 ^ এক্স চেক করা কেবল প্রজন্মকে দ্রুততর করে তোলে কারণ সরাসরি ব্যবহার করে rng.nextLong() % nঅভিন্ন মান দেওয়া হবে (ধরে নিন সমস্ত বিট ভাল)। আপনি চাইলে সেই অংশটিকে উপেক্ষা করতে পারেন।
কেনেটিএম

যদি আমি চাই m <= x <= n, আপনি কীভাবে আপনার সমাধানটি পরিবর্তন করবেন?
বিজে পিটার ডিএলাক্রুজ

6
@BJPeterDeLaCruz: একটি মধ্যবর্তী র্যান্ডম সংখ্যা mএবং nএর মধ্যে একটি র্যান্ডম সংখ্যা সঙ্গে প্রাপ্ত করা যাবে 0এবং n-m, তারপর যোগ m
কেনেটিএম

84

ThreadLocalRandom

ThreadLocalRandomএকটি nextLong(long bound)পদ্ধতি আছে

long v = ThreadLocalRandom.current().nextLong(100);

nextLong(long origin, long bound)আপনার যদি 0 ছাড়া অন্য কোনও উত্সের প্রয়োজন হয় তবে এটিও রয়েছে উত্স (সমেত) এবং সীমাবদ্ধ (একচেটিয়া) পাস করুন।

long v = ThreadLocalRandom.current().nextLong(10,100); // For 2-digit integers, 10-99 inclusive.

SplittableRandomএকই nextLongপদ্ধতি রয়েছে এবং যদি আপনি সংখ্যার পুনরায় উত্পাদনযোগ্য ক্রম চান তবে আপনাকে একটি বীজ চয়ন করতে দেয়।


5
এই উত্তরটি বেশ সরল এবং অতএব সর্বাধিক ভোট দেওয়া একের চেয়ে বেশি কার্যকর।
ইউরিন


75

একটি পরিসরে একটি সংখ্যা (কোনও ইউটিলিটি পদ্ধতি ছাড়াই) উত্পন্ন করার মানক পদ্ধতিটি হ'ল মাত্রার সাথে ডাবলটি ব্যবহার করা:

long range = 1234567L;
Random r = new Random()
long number = (long)(r.nextDouble()*range);

আপনাকে 0 (অন্তর্ভুক্ত) এবং ব্যাপ্তির (একচেটিয়া) মধ্যে একটি দীর্ঘ সময় দেবে। একইভাবে যদি আপনি x এবং y এর মধ্যে একটি সংখ্যা চান:

long x = 1234567L;
long y = 23456789L;
Random r = new Random()
long number = x+((long)(r.nextDouble()*(y-x)));

123456789 (একচেটিয়া) এর মাধ্যমে আপনাকে 1234567 (সহ) থেকে একটি দীর্ঘ সময় দেবে

দ্রষ্টব্য: প্রথম বন্ধনী পরীক্ষা করুন, কারণ দীর্ঘস্থানে castালাইয়ের ক্ষেত্রে গুণণের চেয়ে বেশি অগ্রাধিকার রয়েছে।


5
আমার প্রথম ধারণাটি ঠিক এই ছিল। তবে এটি কিছুটা অবহেলিত বলে মনে হচ্ছে। এবং আমি বিতরণের অভিন্নতার বিষয়ে উদ্বিগ্ন (এটি আসলে আমার এটির প্রয়োজন নয়, আমি কেবল এটি সঠিকভাবে করতে চাই)
উইলিয়াস নরম্যান্টাস

6
দয়া করে এটি কখনও ব্যবহার করবেন না। আউটপুট মোটেও অভিন্ন নয়।
নবীন

2
সবচেয়ে বড় সমস্যাটি হ'ল রাউন্ডিংটি সর্বনিম্ন বিটটিকে খুব অচিরাচর করে তোলে। এছাড়াও, boundবৃহত্তম সংখ্যার চেয়ে কম হতে হবে যা ডাবল, 2 ^ 53 এ এনকড করা যায়।
আলেকসান্দ্র ডাবিনস্কি

12

উপরের পদ্ধতিগুলি দুর্দান্ত কাজ করে। আপনি যদি অ্যাপাচি কমন্স (org.apache.commons.math.random) ব্যবহার করছেন তবে র্যান্ডমডাটা দেখুন। এটির একটি পদ্ধতি রয়েছে: পরের দীর্ঘ (দীর্ঘ নিম্ন, দীর্ঘ উপরের)

http://commons.apache.org/math/userguide/random.html

http://commons.apache.org/math/api-1.1/org/apache/commons/math/random/RandomData.html#nextLong(long,%20long)


3
উত্তরোত্তর জন্য: র্যান্ডমডেটা ৪.০ এ অবমাননিত। Commons.apache.org/proper/commons-math/apidocs/org/apache/…
মাইকেল

11

'%' অপারেটরটি ব্যবহার করুন

resultingNumber = (r.nextLong() % (maximum - minimum)) + minimum;

'%' অপারেটর ব্যবহার করে, আপনার সর্বাধিক মান দ্বারা বিভক্ত হয়ে আমরা বাকী অংশটি গ্রহণ করি। এটি আমাদের 0 (অন্তর্ভুক্ত) থেকে বিভাজক (একচেটিয়া) পর্যন্ত কেবল সংখ্যার সাথে ছেড়ে দেয়।

উদাহরণ স্বরূপ:

public long randLong(long min, long max) {
    return (new java.util.Random().nextLong() % (max - min)) + min;
}

এটি দুর্দান্ত, তবে আপনার চেক করা উচিতif (max == min)
khcpietro

এবং এছাড়াও দেখুনif (nextLong() >= 0)
khcpietro

6
এফওয়াইআই: এটি সর্বদা অভিন্ন বিতরণ দেয় না এবং কিছু বড় ব্যাপ্তির জন্য এটি খারাপ। উদাহরণস্বরূপ, যদি min = 0এবং max = 2 * (MAX_LONG / 3), তাহলে আপনি দুইবার হিসাবে সম্ভবত করছি একটি মান পেতে [0, MAX_LONG / 3]হিসাবে আপনি এক পেতে [MAX_LONG / 3, 2 * (MAX_LONG / 3)]
নিক

এই কোডটি কাজ করবে না। যদি nextLongএকটি নেতিবাচক মান প্রদান করে তবে বাকী অংশগুলি নেতিবাচক হবে এবং মানটি ব্যাপ্তির বাইরে থাকবে।
আর্নৌদ

3

কেনেটিমের জবাব আরও উন্নত করা: জাভা 8-এ আসল বাস্তবায়নকে বিবেচনায় নেওয়া একটি সাবক্লাস বাস্তবায়ন হবে:

public class MyRandom extends Random {
  public long nextLong(long bound) {
    if (bound <= 0) {
      throw new IllegalArgumentException("bound must be positive");
    }

    long r = nextLong() & Long.MAX_VALUE;
    long m = bound - 1L;
    if ((bound & m) == 0) { // i.e., bound is a power of 2
      r = (bound * r) >> (Long.SIZE - 1);
    } else {
      for (long u = r; u - (r = u % bound) + m < 0L; u = nextLong() & Long.MAX_VALUE);
    }
    return r;
  }
}

আমি জানি এটি একটি পুরানো উত্তর এবং এটি ব্যবহারের সম্ভাবনা নেই, তবে এই অংশটি প্রদর্শনযোগ্যভাবে ভুল: if ((bound & m) == 0) { r = (bound * r) >> (Long.SIZE - 1); } প্রথমত, ইউনিট পরীক্ষাগুলির সাহায্যে এটি দেখানো সহজ যে এটি প্রকৃতপক্ষে [0, আবদ্ধ) মধ্যে সংখ্যা তৈরি করে না। দ্বিতীয়ত, এটি অকারণে বিস্তৃত: r = r & mপছন্দসই ফলাফলটি অর্জন করবে এবং মূলত বর্তমান জাভা 8 বাস্তবায়ন এটি করে। এই উত্তরটি লিখিত হওয়ার পরে বাস্তবায়নটি আলাদা ছিল এমনটি সম্ভব, তবে যা দেখানো হয়েছে তা হতে পারে না।
ই বিশপ

3

আপনি যদি [0, m) এর পরিসরে দীর্ঘ অভিন্ন বিতরণ করা সিউডোর্যান্ডম চান, তবে nextLong()নীচের মতো বর্ণিত পদ্ধতিটির সাথে মিলিয়ে মডুলো অপারেটর এবং পরম মান পদ্ধতি ব্যবহার করে দেখুন:

Math.abs(rand.nextLong()) % m;

randআপনার র্যান্ডম অবজেক্টটি কোথায় ।

মডুলো অপারেটর দুটি সংখ্যা বিভক্ত করে এবং এই সংখ্যাগুলির অবশিষ্টাংশকে আউটপুট করে। উদাহরণস্বরূপ, 3 % 2হয়1 কারণ 3 এবং 2 এর বাকি 1।

যেহেতু nextLong()[- (2 ^ 48), 2 ^ 48) (বা সেই সীমাতে কোথাও) এর পরিসীমাতে দীর্ঘ পরিমাণে অভিন্ন বিতরণ করা সিউডোরান্ডম উত্পন্ন করে, আপনার এটির পরম মান গ্রহণ করতে হবে। যদি আপনি এটি না করেন তবে nextLong()পদ্ধতির মডুলোর একটি নেতিবাচক মান ফেরানোর 50% সম্ভাবনা রয়েছে, যা সীমার বাইরে নয় [0,m ) এর বাইরে নেই।

আপনি প্রথমে যা অনুরোধ করেছিলেন তা হ'ল [0,100) এর পরিসীমাতে সমানভাবে বিতরণ করা সিউডোরডম। নিম্নলিখিত কোডটি এটি করে:

Math.abs(rand.nextLong()) % 100;

1
মডুলো পক্ষপাতদুষ্ট, এলোমেলো স্ট্যাকওভারফ্লো.com
সাইরেনস

2

এটি সম্পর্কে:

public static long nextLong(@NonNull Random r, long min, long max) {
    if (min > max)
        throw new IllegalArgumentException("min>max");
    if (min == max)
        return min;
    long n = r.nextLong();
    //abs (use instead of Math.abs, which might return min value) :
    n = n == Long.MIN_VALUE ? 0 : n < 0 ? -n : n;
    //limit to range:
    n = n % (max - min);
    return min + n;
}

?


ঠিক আছে, ফ্রেমওয়ার্কের সাথে সম্পর্কিত অংশগুলি বাদে (আমার ধারণা)।
দামির ওলেজার

2

নীচের পদ্ধতিটি আপনাকে 10000000000 থেকে 9999999999 এর মধ্যে একটি মান প্রদান করবে

long min = 1000000000L
long max = 9999999999L    

public static long getRandomNumber(long min, long max){

    Random random = new Random();         
    return random.nextLong() % (max - min) + max;

}

যখন আমি দীর্ঘ মিনিট = 1L পুনরায় সেট করি; দীর্ঘ সর্বাধিক = 10 এল; ফলস্বরূপ এলোমেলো সংখ্যাটি সর্বোচ্চ মান ছাড়িয়ে যায়!
রাজ রাজেন

এটি এলোমেলো হওয়া উচিত ne পূর্ববর্তী দীর্ঘ ()% (সর্বাধিক - মিনিট) + মিনিট;
জে যোদিওয়াল

2

থেকে জাভা 8 এপিআই

এপিআই ডক https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long- এর কাছ থেকে প্রকৃত বাস্তবায়ন নেওয়া আরও সহজ হতে পারে - তারা এটিকে এটিতে ব্যবহার করছে লম্বা স্ট্রিম উত্পন্ন। এবং আপনার উত্স প্রশ্নের মতো "0" হতে পারে।

long nextLong(long origin, long bound) {
  long r = nextLong();
  long n = bound - origin, m = n - 1;
  if ((n & m) == 0L)  // power of two
    r = (r & m) + origin;
  else if (n > 0L) {  // reject over-represented candidates
    for (long u = r >>> 1;            // ensure nonnegative
         u + m - (r = u % n) < 0L;    // rejection check
         u = nextLong() >>> 1) // retry
        ;
    r += origin;
  }
  else {              // range not representable as long
    while (r < origin || r >= bound)
      r = nextLong();
  }
  return r;
}

1

র্যান্ডম পৃষ্ঠা থেকে :

পরবর্তী দীর্ঘ পদ্ধতিটি এলোমেলোভাবে শ্রেণি দ্বারা বাস্তবায়িত করা হয়েছে যেমন:

public long nextLong() {
   return ((long)next(32) << 32) + next(32);
}

যেহেতু ক্লাস র্যান্ডম কেবল 48 বিট সহ একটি বীজ ব্যবহার করে, এই অ্যালগরিদম সমস্ত সম্ভাব্য দীর্ঘ মান ফিরে পাবে না।

সুতরাং আপনি যদি একটি পেতে চান তবে আপনি Longইতিমধ্যে পুরো bit৪ বিটের পরিসীমা পাবেন না।

আমি পরামর্শ দেব যে যদি আপনার 2 টির শক্তির কাছে একটি পরিসীমা থাকে তবে আপনি Longসেই স্নিপেটের মতোই এটি তৈরি করুন:

next(32) + ((long)nextInt(8) << 3)

একটি 35 বিট পরিসীমা পেতে, উদাহরণস্বরূপ।


2
তবে ডকুমেন্টেশনটিতে বলা হয়েছে "সমস্ত 2 ^ 64 সম্ভাব্য দীর্ঘ মানগুলি প্রায় (প্রায়) সমান সম্ভাবনার সাথে উত্পাদিত হয়।" সুতরাং স্পষ্টতই পরবর্তী লং () পদ্ধতিতে সমস্ত সম্ভাব্য মান ফিরিয়ে দেওয়া উচিত .. বিটিডাব্লু, বীজের দৈর্ঘ্য মূল্যগুলির বন্টনের সাথে কীভাবে সম্পর্কিত?
ভিলিয়াস নরম্যান্টাস

0

পদ্ধতিগুলি ব্যবহার করা r.nextDouble()উচিত:

long number = (long) (rand.nextDouble()*max);


long number = x+(((long)r.nextDouble())*(y-x));

0
public static long randomLong(long min, long max)
{
    try
    {
        Random  random  = new Random();
        long    result  = min + (long) (random.nextDouble() * (max - min));
        return  result;
    }
    catch (Throwable t) {t.printStackTrace();}
    return 0L;
}

1
আপনার এই Randomদৃষ্টান্তে উদাহরণস্বরূপ তৈরি করা উচিত নয় Throwable, প্রয়োজন না হলে আপনার বা অন্যান্য ব্যতিক্রমগুলি ধরা উচিত নয় , আপনার ব্যবহারের পরিবর্তে কোনও ধরণের লগিং ফ্রেমওয়ার্ক (যেমন এসএলএফ 4 জে) এর সাথে ত্রুটিগুলি লগ করা উচিত printStackTrace
বগুয়ে

0

আপনি যদি জাভা স্ট্রিম ব্যবহার করতে পারেন তবে আপনি নিম্নলিখিতটি চেষ্টা করতে পারেন:

Random randomizeTimestamp = new Random();
Long min = ZonedDateTime.parse("2018-01-01T00:00:00.000Z").toInstant().toEpochMilli();
Long max = ZonedDateTime.parse("2019-01-01T00:00:00.000Z").toInstant().toEpochMilli();
randomizeTimestamp.longs(generatedEventListSize, min, max).forEach(timestamp -> {
  System.out.println(timestamp);
});

এটি দীর্ঘস্থায়ীভাবে প্রদত্ত পরিসরে সংখ্যা তৈরি করবে।


0
import java.util*;

    Random rnd = new Random ();
    long name = Math.abs(rnd.nextLong());

এই কাজ করা উচিত


-4

// সিস্টেমের সময়টিকে একটি ভাল এলোমেলো নম্বর পেতে বীজ মান হিসাবে ব্যবহার করুন

   Random random = new Random(System.currentTimeMillis());
              long x;
             do{
                x=random.nextLong();
             }while(x<0 && x > n); 

// বৃহত্তর বা সমান 0 এবং n এর চেয়ে কম সংখ্যক প্রাপ্ত হওয়া পর্যন্ত লুপ করুন


1
এটি চূড়ান্তভাবে অসুবিধে হতে পারে। যদি n1 হয়, বা 2 বলুন? লুপটি অনেকগুলি পুনরাবৃত্তি সম্পাদন করবে ।
ম্যাগনিলেক্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.