2016-08-27 2 views
2

Создание генератора случайных чисел в Java - просмотр num1 и num2, в каких случаях я бы использовал один из этих методов для создания случайного числа от 1 до 8? Является ли более эффективным, чем другие, любые другие преимущества?Java Math.abs random vs. nextInt()

import java.util.*; 

public class Chpt3 { 
    public static void main(String[] args) { 
    Random rand = new Random(); 
    int num1 = Math.abs(rand.nextInt()) % 8 + 1; 
    int num2 = rand.nextInt(8) + 1; 
    System.out.println(num1); 
    System.out.println(num2); 

    } 
} 
+0

Поскольку вы хотите целое число в диапазоне [1, 9], вы должны использовать rand.nextInt, так как он лучше описывает ваши намерения. Если вы не знаете иначе, внутренние реализации более конкретных функций, как правило, лучше, чем составление их из существующих функций. Тем не менее, Java является скомпилированным языком и использует статический анализ, чтобы сделать многие из этих решений несущественными, канонизируя два шаблона Math.abs (Math.random) и random.nextInt в почти таком же выражении. – Dmitry

ответ

4

Math.abs (rand.nextInt())% 8 + 1;

У этого есть тонкая ошибка. Math.abs (Integer.MIN_VALUE) возвращает MIN_VALUE, который является отрицательным числом. Более простым решением является

(rand.nextInt() & 7) + 1; 

Это всегда будет неотрицательным и будет немного быстрее.

rand.nextInt (8) + 1

Это и быстрее, но, что более важно, яснее, как к тому, что вы пытаетесь достичь. По более поздней причине, а не только по скорости, это лучший выбор.

Примечание: вы можете использовать abs, если вам действительно понравилось это. Однако это не так чисто, как звонок nextInt.

Math.abs(rand.nextInt() % 8) + 1; 
6

nextInt(n) возвращается между 0 и n-1.

Так, чтобы получить от 1 до 8,

int num2 = rand.nextInt(8) + 1; 

Что означает, что ваш второй один является один вам нужно.


Update:

Math.abs(Integer.MIN_VALUE) возвращает отрицательное значение.

Согласно this answer на SO:

Integer.MIN_VALUE is -2147483648, но наибольшее значение 32 бит может содержать целое число является +2147483647. Попытка представить +2147483648 в 32-битном int эффективно «перевернется» до -2147483648. Это связано с тем, что при использовании целых чисел со знаком двоичные представления двоичного кода +2147483648 и -2147483648 равны . Это не проблема, однако, поскольку +2147483648 - считается вне пределов досягаемости.

Для немного больше чтения по этому вопросу, вы можете захотеть, чтобы проверить Первый метод Wikipedia article on Two's complement.

содержит только редкий случай угловой. Вот почему лучше использовать второй, так как это безопасно.

+0

Можете ли вы добавить объяснение, почему вы не первый вариант, который, похоже, делает то же самое? –

+0

@PeterLawrey обновил ответ. –

+2

Он не сказал 'Math.abs (Integer.MIN_VALUE)' return negative - ошибка. Он сказал: «Math.abs (rand.nextInt())% 8 + 1' имеет ошибку, потому что' Math.abs (Integer.MIN_VALUE) 'может (правильно) возвращать отрицательный. – shmosel

1

Вот проблема:

int num1 = Math.abs(rand.nextInt()) % 8 + 1; 

означает, что вы будете первым выбрать число от «Все 2^32 возможных ИНТ значения производятся с (приблизительно) равной вероятностью», а затем после этого вы будете mod ответ на 8. Поскольку мы используем Math.abs(), одна проблема заключается в том, что он может вернуть отрицательное число.

int num2 = rand.nextInt(8) + 1; 

Однако эта версия не будет возвращать отрицательное число и возвращает число от 0 до 8.

Оба кода подходит для достижения того, что вы хотите сделать. Тем не менее, вторая строка кода будет лучше для памяти, в первой версии худшим случаем является то, что вам нужно запомнить номер 2^32. Однако для второй версии вам не обязательно. Другое дело, что, поскольку мы должны использовать меньше методов и меньше вычислений, второй метод будет намного быстрее. В общем, оба метода работают, но вторая версия - лучшая версия, так как она занимает меньше памяти и быстрее работает в целом.

Смежные вопросы