Compare distribution of three random integer algorithm.
python
sadrand
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

sadrand.py 2.9KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #!/usr/bin/python3
  2. import random
  3. import argparse
  4. import math
  5. import sys
  6. import warnings
  7. tqdm = lambda it, **kwargs: iter(it)
  8. def std_rand(args):
  9. result = [0 for _ in range(args.resolution)];
  10. for _ in tqdm(range(args.iter), unit_scale=True, total=args.iter):
  11. result[random.randint(0, args.resolution-1)] += 1
  12. return result
  13. def std_rand_fast(args):
  14. result = [0 for _ in range(args.resolution)];
  15. nbits = math.ceil(math.log2(args.resolution))
  16. for _ in tqdm(range(args.iter), unit_scale=True, total=args.iter):
  17. while True:
  18. rnd = random.getrandbits(nbits)
  19. if rnd < args.resolution:
  20. break
  21. result[rnd] += 1
  22. return result
  23. def rnd_bytes(count, chunk_size=4096):
  24. to_read = count
  25. with open('/dev/urandom', 'br') as rfd:
  26. for _ in range((count // chunk_size) + 1):
  27. read_sz = chunk_size if to_read > chunk_size else to_read
  28. chunk = rfd.read(read_sz)
  29. to_read -= len(chunk)
  30. for res_byte in chunk:
  31. yield res_byte
  32. def generic_rand(args, rnd_fun):
  33. result = [0 for _ in range(args.resolution)];
  34. for rbyte in tqdm(rnd_bytes(args.iter), total=args.iter, unit_scale=True):
  35. result[rnd_fun(rbyte)] += 1
  36. return result
  37. mod_rand = lambda args: generic_rand(args,
  38. lambda rbyte: rbyte % args.resolution)
  39. prop_rand = lambda args: generic_rand(args,
  40. lambda rbyte:(rbyte*(args.resolution)) // 256)
  41. if __name__ == "__main__":
  42. parser = argparse.ArgumentParser();
  43. parser.add_argument('-i', '--iter', type=lambda v: int(v,0),
  44. default=0x100000);
  45. parser.add_argument('-r', '--resolution', type=lambda v: int(v,0),
  46. default=100);
  47. parser.add_argument('-c', '--chunk-size', type=int, default=4096);
  48. parser.add_argument('-R', '--relative', action="store_true",
  49. default=False);
  50. parser.add_argument('-p', '--progress', action="store_true",
  51. default=False);
  52. parser.add_argument('--std', action="store_true", default=False,
  53. help="Use random.randint instead of random.getrandbits")
  54. args = parser.parse_args();
  55. if args.progress:
  56. try:
  57. from tqdm import tqdm
  58. except (NameError, ImportError):
  59. warnings.warn("tqdm module not found, no progress bar")
  60. methods = (std_rand if args.std else std_rand_fast, mod_rand, prop_rand)
  61. results = [method(args) for method in methods]
  62. if args.relative:
  63. for i, result in enumerate(results):
  64. results[i] = [(r / args.iter) * args.resolution for r in result]
  65. for i, res in enumerate(zip(*results)):
  66. if args.relative:
  67. i = i / args.resolution
  68. sys.stdout.write(str(i) + ' ' + (' '.join([str(r) for r in res]))+'\n')