В учебнике "Теория чисел" (автор Бухштаб) есть глава, которая называется - Проблемы аддитивной теории простых чисел
Она начинается с проблемы Гольдбаха, которую тот озвучил в письме к Эйлеру в 1742 году.
Существуют два варианта гипотезы Гольдбаха - бинарный и тернарный.
Тернарный вариант утверждает, что любое нечётное число можно представить в виде суммы трёх простых чисел.
В 2013 году доказана перуанским математиком Харальдом Гельфготтом.
Из этого следует, что любое чётное число — сумма не более чем 4 простых чисел.
Бинарный вариант утверждает, что любое чётное число можно представить в виде суммы двух простых чисел. Является открытой математической проблемой — по состоянию на 2023 год утверждение не доказано. В совокупности с гипотезой Римана включена в список проблем Гильберта под номером 8.
Различные математики внесли свой вклад в решение этой гипотезы.
Виноградов в 1937 году показал, что почти все чётные числа представимы в виде суммы двух простых чисел.
В 1930 году Шнирельман доказал, что любое целое число представимо в виде суммы не более чем 800000 простых чисел. Этот результат многократно улучшался, так, в 1995 году Оливье Рамаре доказал, что любое чётное число — сумма не более чем 6 простых чисел.
На апрель 2012 года бинарная гипотеза Гольдбаха была проверена для всех чётных чисел, не превышающих 4 ⋅ 10^18.
В этой статье выкладывается программа, которая решает следующую задачу:
Берется ряд простых чисел в каком-то диапазоне
Составляются все возможные комбинации из сумм подряд идущих простых чисел из этой последовательности
Задача - найти простое число, которое можно представить в виде таких сумм максимально возможным количеством вариантов.
Результаты:
Если взять все простые числа до одного миллиона, то среди этих простых чисел найдется одно простое число
442019
которое раскладываетя 6-ю способами:
Первый способ для числа 442019 - ряд начинается с простого числа 419 и заканчивается простым числом 2621, всего в этом ряду 301 подряд идущих простых чисел, без пропусков.
В последнем шестом способе всего 3 подряд идущих числа
Если взять все простые числа до 10 миллионов, то среди этих простых чисел найдется одно простое число
3634531
которое раскладываетя 7-ю способами:
Для того, чтобы проверить все простые числа в диапазоне до миллиарда, требуется уже более 100 гигабайт оперативной памяти.
Очевидно, что среди них наверняка найдется одно простое число, которое раскладывается 9-ю способами
Отсюда вытекает лемма: Существует бесконечно большое простое число, которое можно разложить на суммы подряд идущих простых таким количеством способов, которое равно числу разрядов этого числа.
Код
import (
"fmt"
"math"
"math/big"
"os"
"time"
"sync"
)
func get_primes(nn int64) ([]int64){
//const N = {nn}
var x, y, n int64
nsqrt := math.Sqrt(float64(nn))
//is_prime := [nn]bool{}
is_prime := make([]bool, nn)
for x = 1; float64(x) <= nsqrt; x++ {
for y = 1; float64(y) <= nsqrt; y++ {
n = 4*(x*x) + y*y
if n <= nn && (n%12 == 1 || n%12 == 5) {
is_prime[n] = !is_prime[n]
}
n = 3*(x*x) + y*y
if n <= nn && n%12 == 7 {
is_prime[n] = !is_prime[n]
}
n = 3*(x*x) - y*y
if x > y && n <= nn && n%12 == 11 {
is_prime[n] = !is_prime[n]
}
}
}
for n = 5; float64(n) <= nsqrt; n++ {
if is_prime[n] {
for y = n*n; y < nn; y += n*n {
is_prime[y] = false
}
}
}
is_prime[2] = true
is_prime[3] = true
primes := make([]int64, 0)
for x = 2; x < int64(len(is_prime)-1); x++ {
if is_prime[x] {
if x > 1 {
primes = append(primes, x)
}
}
}
return primes
}
func find_super_primes(prime *big.Int, primes []*big.Int , primess map[string]int , start_date time.Time, max_prime *big.Int){
i := 0
for{
j := i
sum_primes := big.NewInt(0)
_str := fmt.Sprintf("\n%v= ", prime)
_c := 0
for{
sum_primes.Add(sum_primes, primes[j])
if sum_primes.Cmp(max_prime) == 1 { break }
if _c == 0 {_str += fmt.Sprintf("%v + ... + ", primes[j]) }
//_str += fmt.Sprintf("%v + ", primes[j])
_c += 1
if sum_primes.Cmp(prime) == 0 && _c > 1{
_str = fmt.Sprintf("%v%v (%v)", _str, primes[j], _c)
fmt.Printf(_str)
}
j += 1
if j >= len(primes){ break }
}
i += 1
if i >= len(primes){ break }
}
}
func (c *SafeMapSuperPrime) find_primes(primes []*big.Int , primess map[string]int , i int, start_date time.Time, max_prime *big.Int){
c.mu.Lock()
j := i
sum_primes := big.NewInt(0)
for{
if j >= len(primes){ break }
sum_primes.Add(sum_primes, primes[j])
if sum_primes.Cmp(max_prime) == 1 { break }
sps := sum_primes.String()
_, _ok := primess[sps]
if _ok {
_, ok := c.super_primes[primess[sps]]
if ok {
if i != j {
c.super_primes[primess[sps]] += 1
}
} else {
if i != j {
c.super_primes[primess[sps]] = 1
}
}
}
j += 1
if j >= len(primes){ break }
}
c.mu.Unlock()
}
type SafeMapSuperPrime struct {
mu sync.Mutex
super_primes map[int]int
}
func (c *SafeMapSuperPrime) get_super_primes() map[int]int {
c.mu.Lock()
defer c.mu.Unlock()
return c.super_primes
}
func main(){
start_date := time.Now()
primes := make([]*big.Int, 0)
primess := make(map[string]int)
max_prime := big.NewInt(1)
__primes := get_primes(1000000)
_primes := make([]*big.Int, 0)
_c:=0
for {
d := big.NewInt(0).Set(big.NewInt(__primes[_c]))
_primes = append(_primes, d)
_c += 1
if _c == len(__primes){break}
}
__primes = make([]int64, 0)
_i := 0
for _, _p := range _primes {
primes = append(primes, _p)
primess[_p.String()] = _i
_i += 1
max_prime.Set(_p)
}
_primes = make([]*big.Int, 0)
finish_date := time.Since(start_date)
fmt.Printf("%v %v \n", len(primes), finish_date.Seconds())
c := SafeMapSuperPrime{super_primes: make(map[int]int)}
i := 0
for{
go c.find_primes(primes, primess, i, start_date, max_prime)
i += 1
if i >= len(primes)-1{ break }
//if i >= i_max { break }
}
primess = make(map[string]int)
time.Sleep(time.Second)
for k, v := range c.get_super_primes() {
if v >= 6 {
fmt.Printf("\n!!! count=%v prime=%v\n", v, primes[k])
test_prime := big.NewInt(0)
test_prime.SetString(primes[k].String(), 0)
find_super_primes(test_prime, primes, primess, start_date, max_prime)
}
}
finish_date = time.Since(start_date)
fmt.Printf("\n%v \n", finish_date.Seconds())
os.Exit(0)
}