Làm cách nào để tạo một số ngẫu nhiên trong một phạm vi nhưng loại trừ một số, mà không tiếp tục tạo và kiểm tra xem số được tạo có phải là số mà tôi muốn loại trừ không?Làm cách nào để tạo một số ngẫu nhiên trong một phạm vi nhưng loại trừ một số?
Trả lời
Một giải pháp khả thi mà không cần tái tạo các ngẫu nhiên mỗi lần là sử dụng các thuật toán sau đây :
public int getRandomWithExclusion(Random rnd, int start, int end, int... exclude) {
int random = start + rnd.nextInt(end - start + 1 - exclude.length);
for (int ex : exclude) {
if (random < ex) {
break;
}
random++;
}
return random;
}
Phương pháp này có thể được gọi với tham chiếu mảng, ví dụ:
int[] ex = { 2, 5, 6 };
val = getRandomWithExclusion(rnd, 1, 10, ex)
hoặc bằng cách trực tiếp chèn số vào cuộc gọi:
val = getRandomWithExclusion(rnd, 1, 10, 2, 5, 6)
Nó tạo ra một số ngẫu nhiên (int) giữa start
và end
(cả bao gồm) và không cung cấp cho bạn bất kỳ số đó được chứa trong mảng exclude
. Tất cả các số khác xảy ra với xác suất bằng nhau. Lưu ý rằng các ràng buộc sau đây phải giữ: exclude
được sắp xếp tăng dần và tất cả các số nằm trong phạm vi được cung cấp và tất cả các số này đều khác nhau.
+1 cùng một suy nghĩ tại đây không. Nhưng tôi muốn kiểm tra 'ngẫu nhiên
@ Mã điều chỉnh được sinh ra để kết hợp đề xuất của bạn. – Howard
@Fatal, @Howard, đây là giải pháp cực kỳ thông minh. Bạn đã học nó ở đâu hoặc bạn đã nghĩ ra sao? Lúc đầu, tôi đã chắc chắn điều này sẽ không làm việc nhưng sau khi bước qua nó tôi thấy nó chắc chắn không hoạt động và tôi rất ấn tượng. Đối với mã hàng ngày tôi sẽ không muốn nhìn thấy điều này trong codebase của chúng tôi bởi vì nó cho tốc độ tại đắt tiền dễ đọc. – Paul
Tạo bản đồ lấy đầu ra của một hàm ngẫu nhiên không có giới hạn phạm vi và ánh xạ nó tới phạm vi bạn muốn với giới hạn.
Ví dụ, nếu tôi muốn có một int ngẫu nhiên từ 1-10 nhưng không bao giờ 7 tôi có thể làm một cái gì đó như thế này:
int i = rand(1, 9);
if i>=7
i++;
return i;
Chừng nào bạn đảm bảo rằng bản đồ của bạn là 1: 1, bạn có thể tránh được xoay chiều ngẫu nhiên của hàm rand
.
Đường vòng khác sẽ tốt hơn: tạo số từ 1 đến 8 và bản đồ 7 và 8 đến 8 và 9. Cách này bạn giữ bản phân phối. – keuleJ
@keuleJ: bạn quên lập bản đồ từ 9 đến 10 Bên cạnh đó, nó chỉ là một ví dụ tầm thường. Bất kỳ bản đồ nào bạn đưa ra sẽ cụ thể cho thuật toán của bạn. Miễn là bản đồ của bạn nhất quán (mỗi bản đồ đầu vào có thể có cùng số lượng đầu ra và mỗi đầu ra mong muốn được ánh xạ tới bởi cùng một số đầu vào có thể), bạn sẽ giữ bản phân phối. –
@Ax bạn nói đúng. Nhưng bạn đã vẽ bản đồ 7 và 8 thành 8. Thật dễ dàng để làm hỏng sự phân phối trong các loại thuật toán này ... – keuleJ
Tùy thuộc vào danh sách các số ngẫu nhiên bạn loại trừ bao nhiêu, tôi sẽ chỉ tạo các số của bạn và kiểm tra xem nó có nằm trong dãy số bị loại trừ hay không - nếu có, chỉ cần loại bỏ nó. Tôi biết bạn không muốn kiểm tra mọi lúc, nhưng tôi không thể nghĩ ra một cách khác ngoài việc chỉ định phạm vi một cách rõ ràng và nếu bạn có nhiều hơn 5 số bạn đang loại trừ, điều đó có thể tồi tệ hơn một chút.
Cái gì mà có thể làm việc và áp dụng cho cả int và số đôi có thể giống như:
public int getRandomNumberWithExclusion(int start, int end)
{
Random r = new Random();
int result = -1;
do
{
result = start + r.nextInt(end - start);
}//do
while(!isAllowed(result));
return result;
}//met
private boolean isAllowed(int number)
{
//your test for restricted values here
}//met
Kính trọng, Stéphane
"[...] mà không tiếp tục tạo và kiểm tra xem số được tạo có phải là số mà tôi muốn loại trừ" –
Các aproach tốt nhất mà bạn có thể làm theo để ngẫu nhiên số, ngoại trừ một số là chọn các số mà bạn muốn đầu tiên và sau đó chọn ngẫu nhiên các con số được chọn. Ví dụ: trong mã giả:
List<Number> numbers;
numbers.add(1);
numbers.add(2);
numbers.add(3);
//You can do a "for" without adding the excluded numbers..
//Then, your randomizer could be...
public Number getRandoNumber() {
int index = Random.get(0, numbers.size());
return numbers.get(index);
}
Bây giờ, bạn không cần phải kiểm tra xem "số được tạo" có được phép hay không, vì nó không tồn tại chút nào.
Nếu bạn không muốn họ lặp lại, bạn có thể làm điều gì đó như:
Collections.shuffle(numbers);
public Number getRandomNotRepeat() {
if(numbers.size() == 0)
throw new RuntimeException("No more numbers");
Number n = numbers.get(0);
numbers.removeFirst();
return n;
}
này được tất cả các mã giả, sao chép và dán đừng!
/**
* @param start start of range (inclusive)
* @param end end of range (exclusive)
* @param excludes numbers to exclude (= numbers you do not want)
* @return the random number within start-end but not one of excludes
*/
public static int nextIntInRangeButExclude(int start, int end, int... excludes){
int rangeLength = end - start - excludes.length;
int randomInt = RANDOM.nextInt(rangeLength) + start;
for(int i = 0; i < excludes.length; i++) {
if(excludes[i] > randomInt) {
return randomInt;
}
randomInt++;
}
return randomInt;
}
Ý tưởng là giảm phạm vi trong đó số ngẫu nhiên được tạo ra cho sự khác biệt giữa bắt đầu và kết thúc trừ số lượng trong phạm vi đó bị loại trừ.
Vì vậy, bạn có được độ dài dải ô giống với số lượng các số hợp lệ có thể có. Nói cách khác: Bạn đã xóa tất cả các lỗ khỏi phạm vi.
Sau khi tạo số ngẫu nhiên bạn đã đặt "lỗ" trở lại trong phạm vi. Điều này có thể đạt được bằng cách tăng số lượng được tạo miễn là có số bị loại trừ thấp hơn hoặc bằng số được tạo. Các số loại trừ thấp hơn là "lỗ" trong phạm vi trước số được tạo. Và số được tạo sẽ được chuyển sang phải cho mọi lỗ trước số đó.
+1 cho lời giải thích tiếng Anh – deinocheirus
câu trả lời hay vì nhận xét javadoc và mã có ý nghĩa –
Tôi nghĩ câu hỏi bổ sung là: Các con số bạn muốn exlcude là gì? Chúng có đại diện cho một số loại trong phạm vi hoặc chúng là hoàn toàn ngẫu nhiên?
Nếu đó là một loạt các số điện thoại bạn muốn bỏ qua, bạn có thể tạo ra các số ngẫu nhiên của bạn từ bên trong vài bộ đại diện cho số chỉ có giá trị:
rand(1,9);
rand(15,19);
rand(22,26);
cách này bạn chắc chắn sẽ không bao giờ chọn loại trừ: < 0,10,11,12,13,14,20,21,> 27
Sau đó, khi bạn nhận được 3 số, bạn lại có thể chọn ngẫu nhiên một trong số chúng.
Nếu số bị loại trừ ở khắp nơi, tôi sợ bạn phải kiểm tra nó mỗi lần đối với một số loại tập hợp số bị loại trừ.
Tôi phải rút lại tuyên bố trước đó của mình. Mặc dù điều này có vẻ như là một ý tưởng hay nhưng nó thực sự làm lệch kết quả trừ khi mỗi phạm vi "được chọn" có kích thước bằng nhau. Giả sử tôi muốn loại trừ số 2 khỏi phạm vi từ 0 đến 10, số 0 và 1 sẽ xuất hiện hai lần và thường xuyên hơn các số còn lại. Để khắc phục điều này, bạn phải ưu tiên chọn số ngẫu nhiên đến từ phạm vi lớn hơn, nhưng tôi không chắc chắn cách điều chỉnh và duy trì phân phối đồng đều. – Carcigenicate
loại trừ số nên có trong tham số phạm vi
private int GiveMeANumber(int range,int... exclude)
{
Set<Integer> integers=new HashSet<>();
int count=range;
for(int i=0;i<count;i++)
integers.add(i);
integers.removeAll(Arrays.asList(exclude));
int index = new Random().nextInt(range - exclude.length);
count=0;
for (int value:integers){
if(count==index)
return value;
count++;
}
return 0;
}
- 1. Số ngẫu nhiên trong một phạm vi
- 2. Cách lấy một số ngẫu nhiên từ một phạm vi, ngoại trừ một số giá trị
- 3. Tạo một số ngẫu nhiên trong phạm vi?
- 4. Tạo một số ngẫu nhiên trong một phạm vi bằng cách sử dụng C#
- 5. Tạo một số nguyên ngẫu nhiên trong một phạm vi trong Haskell
- 6. Tạo một đôi ngẫu nhiên trong một phạm vi
- 7. Tạo một số ngẫu nhiên gấp đôi của một phạm vi nhất định trong Java
- 8. Số ngẫu nhiên giữa hai phạm vi
- 9. Tạo một số ngẫu nhiên trong phạm vi 0-9 trong x86 8086 Hội
- 10. Tạo một số ngẫu nhiên từ một số khác
- 11. Làm cách nào để chọn 1 số ngẫu nhiên từ 2 phạm vi số khác nhau?
- 12. Tạo cùng một chuỗi số ngẫu nhiên
- 13. Nhận số nguyên ngẫu nhiên trong phạm vi (x, y]
- 14. Tạo một dãy các số ngẫu nhiên
- 15. Tạo một số ngẫu nhiên giữa nhiều khoảng
- 16. Làm cách nào để truyền một trình tạo số ngẫu nhiên C++ 11 cho một hàm?
- 17. Tạo một bộ tạo số giả ngẫu nhiên trong C#
- 18. cách tạo một số các số thập phân ngẫu nhiên giữa 0 và 1
- 19. Làm cách nào để tạo số ngẫu nhiên trong Dart?
- 20. Tạo một số thập phân ngẫu nhiên trong C#
- 21. Cách tạo số "ngẫu nhiên" nhưng cũng "duy nhất"?
- 22. Làm cách nào để tạo một số nguyên 256 bit ngẫu nhiên trong Dart?
- 23. Làm cách nào để tạo một số giả ngẫu nhiên mật mã trong C#?
- 24. Làm cách nào để tạo một đường dẫn ngẫu nhiên?
- 25. Làm thế nào để tạo ra một số năm chữ số ngẫu nhiên Java
- 26. Làm cách nào để nhập toàn bộ gói nhưng loại trừ một số gói trong Clojure?
- 27. Làm cách nào để tạo số ngẫu nhiên trên iPhone?
- 28. java - Làm thế nào để tạo một mảng int với các số ngẫu nhiên xáo trộn trong một phạm vi nhất định
- 29. Làm cách nào để gán một số ngẫu nhiên cho một biến?
- 30. cố gắng tìm một trình tạo số ngẫu nhiên
bạn muốn có một int hoặc hai số ngẫu nhiên? – Snicolas
Bạn có quá nhiều loại trừ trong phạm vi của mình mà rất có thể sẽ bị trúng một số bị loại trừ? –