Разберем ошибки, допущенные Сергеевной!
Что бы не быть голословным, скачал QB64, все примеры будем рассматривать на нем, хотя замечания общие и с небольшими уточнениями подойдут и для других ЯП (языков программирования)!
Известно, что под хранение числовых данных выделяется некоторое фиксированное количество памяти! Например, если для хранения целого числа используется 2 байта памяти, то мы можем представить или число со знаком в диапазоне -32768..32767 или число без знака в диапазоне 0..65535! Выйти за пределы этих диапазонов не расходуя лишней памяти невозможно! Надеюсь, не надо объяснять, почему именно такие диапазоны? Это общее замечание! Теперь перейдем к изучению данного вопроса в рамках этого Бейсика!
1. Что выдает RND?!
Простая программа для тесте:
Запускаем и смотрим! Получаем дробное число от 0 до 1, например: .7055475
Сколько ни запуская программу, она выдает одно и тоже! Все дело в том, что никаких случайных чисел тут нет, есть генератор ПСЕВДО случайных чисел, который работает по определенному (причем достаточно простому) алгоритму! Чтобы получить число, кажущееся случайным, надо провести регенерацию счетчика случайных чисел в соответствии с текущим временем: RANDOMIZE TIMER!
Теперь обратите внимание на точность полученного числа (количество знаков после десятичной точки)! Их всего 7! Проще говоря, с помощью одного RND мы не можем получить число более чем из 7 цифр! Ни какой речи о том, чтобы применять программу Сергеевной для генерации 12-значных чисел и быть не может! Естественно, если не внести в нее определенные изменения (которые выходят за рамки просто подправить 3 числа)! Об этом ниже!
2. Какова максимальная разрядность десятичных чисел?!
Программа для теста:
Очевидно, что A <> B, но программа выдает ответ A = B. Все дело в том, что мы вышли за пределы точности представления чисел (в QB64 оказалось, что эти пределы всего 7 цифр)! То есть никакой речи о сравнении двух чисел из 12 цифр и быть не может! Результат будет заведомо непредсказуемым!
3. Почему у Сергеевой программа подбора 12-значного числа работала быстро?!
Ответ прост и вытекает из предыдущих рассуждений! Все дело в том, что реально эта программа подбирала всего 7 цифр, а не 12!
4. А можно ли как-то написать программу правильно?!
Попытаемся... Во-первых, можно работать не с числами, а со строками! Но работа со строками будет иметь дополнительные накладные расходы на формирование строки, то есть она будет работать медленнее! Во-вторых, можно разбить одно большое число на несколько меньших, например, подбор одного 12-значного числа и четыре 3-значных с точки зрения теории вероятности задачи эквивалентные!
И того, программу Сергеевны надо было переписать примерно так:
Для 6-значного числа:
Считает количество повторений и время в секундах, затраченное на поиск! 6-значное число ищет очень быстро! Жирным выделил то, что надо менять для увеличения количества цифр!
Приведу свои результате для разного количества цифр и время работы программы:
6 цифр - 0.05 секунды, примерно полмиллиона итераций!
7 цифр - 0.9 секунд, около 5 миллионов итераций!
8 цифр - программа зациклилась!!!
Теоретически 8 цифр должны были отработать секунд за 10, обработав примерно 50 миллионов итераций! Но тут возникает иная проблема, проблема в том, что мы не можем генерировать случаынйе числа, а только ПСЕВДО случайные! На эту проблему я вам уже указывал в своих сообщениях выше, но вы тогда пропустили замечание мимо ушей, видимо, просто не поняв, о чем шла речь! Псевдослучайный генератор способен полностью покрыть случайными числами только некоторый диапазон! Из наших тестов видно, что он лежит в пределах до 7 цифр, что вполне логично, учитывая точность QB64, то есть невозможно получить все последовательности длинной более 7 символов, некоторые из них вообще никогда не будут выпадать!
5. Маленькое замечание на счет RANDOMIZE TIMER!
Я его вывел за цикл, вызывая один раз при старте программы! Если хотите, подведите го под цикл (например, строкой 45), но нет никаких причин вызывать его каждый раз хотя бы потому, что за одну итерацию время, получаемое по TIMER с точностью до сотых секунды, не успевает измениться! Простой пример для проверки:
Что бы не быть голословным, скачал QB64, все примеры будем рассматривать на нем, хотя замечания общие и с небольшими уточнениями подойдут и для других ЯП (языков программирования)!
Известно, что под хранение числовых данных выделяется некоторое фиксированное количество памяти! Например, если для хранения целого числа используется 2 байта памяти, то мы можем представить или число со знаком в диапазоне -32768..32767 или число без знака в диапазоне 0..65535! Выйти за пределы этих диапазонов не расходуя лишней памяти невозможно! Надеюсь, не надо объяснять, почему именно такие диапазоны? Это общее замечание! Теперь перейдем к изучению данного вопроса в рамках этого Бейсика!
1. Что выдает RND?!
Простая программа для тесте:
10 PRINT RND
Запускаем и смотрим! Получаем дробное число от 0 до 1, например: .7055475
Сколько ни запуская программу, она выдает одно и тоже! Все дело в том, что никаких случайных чисел тут нет, есть генератор ПСЕВДО случайных чисел, который работает по определенному (причем достаточно простому) алгоритму! Чтобы получить число, кажущееся случайным, надо провести регенерацию счетчика случайных чисел в соответствии с текущим временем: RANDOMIZE TIMER!
Теперь обратите внимание на точность полученного числа (количество знаков после десятичной точки)! Их всего 7! Проще говоря, с помощью одного RND мы не можем получить число более чем из 7 цифр! Ни какой речи о том, чтобы применять программу Сергеевной для генерации 12-значных чисел и быть не может! Естественно, если не внести в нее определенные изменения (которые выходят за рамки просто подправить 3 числа)! Об этом ниже!
2. Какова максимальная разрядность десятичных чисел?!
Программа для теста:
10 A = 123456789
20 B = 123456790
30 IF A = B THEN PRINT "A = B" ELSE PRINT "A <> B"
20 B = 123456790
30 IF A = B THEN PRINT "A = B" ELSE PRINT "A <> B"
Очевидно, что A <> B, но программа выдает ответ A = B. Все дело в том, что мы вышли за пределы точности представления чисел (в QB64 оказалось, что эти пределы всего 7 цифр)! То есть никакой речи о сравнении двух чисел из 12 цифр и быть не может! Результат будет заведомо непредсказуемым!
3. Почему у Сергеевой программа подбора 12-значного числа работала быстро?!
Ответ прост и вытекает из предыдущих рассуждений! Все дело в том, что реально эта программа подбирала всего 7 цифр, а не 12!
4. А можно ли как-то написать программу правильно?!
Попытаемся... Во-первых, можно работать не с числами, а со строками! Но работа со строками будет иметь дополнительные накладные расходы на формирование строки, то есть она будет работать медленнее! Во-вторых, можно разбить одно большое число на несколько меньших, например, подбор одного 12-значного числа и четыре 3-значных с точки зрения теории вероятности задачи эквивалентные!
И того, программу Сергеевны надо было переписать примерно так:
Для 6-значного числа:
10 A1 = 123: A2 = 456: MUL1 = 1000: MUL2 = 1000
20 RANDOMIZE TIMER
30 START = TIMER: CNT = 0
40 R1 = INT(RND * MUL1): R2 = INT(RND * MUL2)
50 CNT = CNT + 1
60 IF R1 <> A1 OR R2 <> A2 THEN GOTO 40
70 PRINT "FIND:", R1; R2
80 PRINT "COUNT:", CNT
90 PRINT "TIME:", TIMER - START
20 RANDOMIZE TIMER
30 START = TIMER: CNT = 0
40 R1 = INT(RND * MUL1): R2 = INT(RND * MUL2)
50 CNT = CNT + 1
60 IF R1 <> A1 OR R2 <> A2 THEN GOTO 40
70 PRINT "FIND:", R1; R2
80 PRINT "COUNT:", CNT
90 PRINT "TIME:", TIMER - START
Считает количество повторений и время в секундах, затраченное на поиск! 6-значное число ищет очень быстро! Жирным выделил то, что надо менять для увеличения количества цифр!
Приведу свои результате для разного количества цифр и время работы программы:
6 цифр - 0.05 секунды, примерно полмиллиона итераций!
7 цифр - 0.9 секунд, около 5 миллионов итераций!
8 цифр - программа зациклилась!!!
Теоретически 8 цифр должны были отработать секунд за 10, обработав примерно 50 миллионов итераций! Но тут возникает иная проблема, проблема в том, что мы не можем генерировать случаынйе числа, а только ПСЕВДО случайные! На эту проблему я вам уже указывал в своих сообщениях выше, но вы тогда пропустили замечание мимо ушей, видимо, просто не поняв, о чем шла речь! Псевдослучайный генератор способен полностью покрыть случайными числами только некоторый диапазон! Из наших тестов видно, что он лежит в пределах до 7 цифр, что вполне логично, учитывая точность QB64, то есть невозможно получить все последовательности длинной более 7 символов, некоторые из них вообще никогда не будут выпадать!
5. Маленькое замечание на счет RANDOMIZE TIMER!
Я его вывел за цикл, вызывая один раз при старте программы! Если хотите, подведите го под цикл (например, строкой 45), но нет никаких причин вызывать его каждый раз хотя бы потому, что за одну итерацию время, получаемое по TIMER с точностью до сотых секунды, не успевает измениться! Простой пример для проверки:
10 FOR N = 1 TO 20
20 PRINT TIMER
30 NEXT
20 PRINT TIMER
30 NEXT
Комментарий