PHP « Очень большое число + поиск простых в диапазоне на PHP

Мне необходимо найти произведение всех простых чисел на огромном диапазоне от 1000000 до 2000000.

Делал я это на php, простые числа я нахожу, но вот с их произведением у меня проблема... числа слишком большие, поэтому php выводит вместо произведения "INF" !!!

Разбиение на более мелкие участки не очень то помогает, их будет тысяч 10 или даже больше, может кто-нибудь портирует на другой язык, где можно работать с такими числами... Или подскажет как сделать это в php

Вот сам алгоритм:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .php.geshi_code {font-family:monospace;} .php.geshi_code .imp {font-weight: bold; color: red;} .php.geshi_code .kw1 {color: #b1b100;} .php.geshi_code .kw2 {color: #000000; font-weight: bold;} .php.geshi_code .kw3 {color: #990000;} .php.geshi_code .co1 {color: #666666; font-style: italic;} .php.geshi_code .co2 {color: #666666; font-style: italic;} .php.geshi_code .co3 {color: #0000cc; font-style: italic;} .php.geshi_code .co4 {color: #009933; font-style: italic;} .php.geshi_code .coMULTI {color: #666666; font-style: italic;} .php.geshi_code .es0 {color: #000099; font-weight: bold;} .php.geshi_code .es1 {color: #000099; font-weight: bold;} .php.geshi_code .es2 {color: #660099; font-weight: bold;} .php.geshi_code .es3 {color: #660099; font-weight: bold;} .php.geshi_code .es4 {color: #006699; font-weight: bold;} .php.geshi_code .es5 {color: #006699; font-weight: bold; font-style: italic;} .php.geshi_code .es6 {color: #009933; font-weight: bold;} .php.geshi_code .es_h {color: #000099; font-weight: bold;} .php.geshi_code .br0 {color: #009900;} .php.geshi_code .sy0 {color: #339933;} .php.geshi_code .sy1 {color: #000000; font-weight: bold;} .php.geshi_code .st0 {color: #0000ff;} .php.geshi_code .st_h {color: #0000ff;} .php.geshi_code .nu0 {color: #cc66cc;} .php.geshi_code .nu8 {color: #208080;} .php.geshi_code .nu12 {color: #208080;} .php.geshi_code .nu19 {color:#800080;} .php.geshi_code .me1 {color: #004000;} .php.geshi_code .me2 {color: #004000;} .php.geshi_code .re0 {color: #000088;} .php.geshi_code span.xtra { display:block; }

<?php
//1000000-2000000
$p = 1; //Это произведение

for ($i = 1000000; $i<=2000000; $i++)
  {
  $no = 0; //Нужно для определения простоты числа ниже
 
  if ($i%2 != 0) //Проверка на четность
    {
    $k = sqrt($i);
      for ($d = 2; $d<=$k; $d++)
      {
      if ($i%$d == 0)
        {
        $no = 1;
        break;
        }
      }
    if ($no == 0)
      {
      $p = $p*$i;
      }
    }
 
  }
 
echo $p;

?>
 




//Алгорит базируется на том, что верхняя граница перебора делителей
 это квадратный корень из самого числа
 


Очень надеюсь, что здесь есть математики-программисты, которым это под силу (пожалуйста!)

1 ответов


Все, задача решилась на PHP, как ни странно. Во первых вы меня все простите, но я не правильно понял фразу по модулю 23, оказывается надо каждое число делить на 23 и брать остаток. Во вторых с таким подходом успешно разделился промежуток на 2, от миллиона до полтора, и от полтора до двух миллионов. Затем число смогла взять функция bcmul.

Всем большое спасибо!


Можно воспользоваться библиотекой для работы с числами произвольной точности: BC Math.


Почитайте про длинные числа. Вкратце: каждое число представляется в виде массива. Таким образом, если считать, что максимально возможным числом в PHP является 2^31, то массив таких чисел, фактически, это длинное число, записанное в системе с основанием 2^31. А дальше все просто реализуете простую библиотечку с переводом в длинные и обратно и четырьмя арифметическими действиями. Все арифметические действия производятся как в школе - в столбик.


Вот код на Java:


BigInteger p = new BigInteger("1");
mainloop: for (int i = 1000001; i<=2000000; i += 2) {
    if (i % 10001 == 0) {
        System.out.println(i + "\r");
    }
    int k = (int) Math.sqrt(i);
    for (int d = 2; d <= k; d++) {
        if (i % d == 0) {
            continue mainloop;
        }
    }
    p = p.multiply(new BigInteger(String.valueOf(i)));
}
String s = p.toString();
System.out.println(s.charAt(0) + "." + s.substring(1, 10) + "E+" + (s.length() - 1));
 

Выполняется примерно за 45 секунд на C2D@4300. В результате получается 178532434340 цифр.

В Python длинная арифметика включена в стандартные возможности. Для этого в синтаксисе есть суффикс "L" ([1])
На языке Python программа будет выглядеть приблизительно следующим образом:


from math import sqrt

def isPrime(N):
    "Эта функция проверяет число на простоту"
    limit = int(sqrt(N))
    for d in xrange(3, limit+1, 2):
        if N%d==0:
            return False
    return True

p = 1L
for n in xrange(1000001,2000001,2):
    if isPrime(n):
        p *= n

print p
 

Этот скрипт работал около 2-х минут и в результате получилось число, в котором 434340 знаков.

А про алгоритм Евклида не слышали?
И без произведения справитесь.