2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу 1, 2, 3, 4, 5  След.
 
 Как писать быстрые программы
Сообщение23.09.2025, 03:49 
Аватара пользователя
Dmitriy40 в сообщении #1702900 писал(а):
Пример mihaild показывает что чатгпт полезнее ассемблера ... Ну плюс немного навыков программирования (на С).

Ну вот я как раз хотел это обсудить в отдельной теме. Насколько понял, далеко не любой может считать по той программе.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 08:11 
Аватара пользователя
Кстати, перечитал кое-что из темы «Первые и последующие шаги в ассемблере x86/x64»

Установил fasm по новой. Проверил на x64 как работает старая прога GAA для Фибоначчи.

И попросту попросил Квена написать мне код на фасме. Он написал жутко длинную прогу, но она заработала! Я лишь исправил

include 'win64a.inc'

на

include 'INCLUDE\win64axp.inc'

Вывод на экран:
Код:
45th Fibonacci Number:
1134903170

(Прога)

format PE64 console
entry start

include 'INCLUDE\win64axp.inc'

section '.data' data readable writable
fib_num dq 0 ; текущее число Фибоначчи
target dq 45 ; какое число хотим вычислить

buffer rb 32 ; буфер для строки (с запасом)
buf_len dq 0 ; длина строки

msg_title db '45th Fibonacci Number:', 13, 10, 0
len_title = $ - msg_title

newline db 13, 10, 0
stdout_handle dq ?

section '.code' code readable executable
start:
; Получаем хендл stdout
sub rsp, 40 ; теневое пространство + выравнивание
mov ecx, -11 ; STD_OUTPUT_HANDLE
call [GetStdHandle]
mov [stdout_handle], rax

; Вывод заголовка
mov rcx, [stdout_handle]
mov rdx, msg_title
mov r8, len_title
mov r9, buf_len
mov qword [rsp + 32], 0 ; lpReserved (NULL)
call [WriteConsoleA]

; Вычисляем 45-е число Фибоначчи
mov rax, [target]
cmp rax, 0
je print_zero
cmp rax, 1
je print_one

; F(0)=0, F(1)=1
xor rbx, rbx ; F(n-2) = 0
mov rcx, 1 ; F(n-1) = 1
mov rdx, 2 ; n = 2

fib_loop:
cmp rdx, [target]
jg fib_done

; F(n) = F(n-1) + F(n-2)
mov rax, rcx ; rax = F(n-1)
add rax, rbx ; rax = F(n)
mov rbx, rcx ; F(n-2) = F(n-1)
mov rcx, rax ; F(n-1) = F(n)
inc rdx
jmp fib_loop

fib_done:
mov [fib_num], rcx

; Конвертируем число в строку
mov rax, [fib_num]
mov rdi, buffer + 31
mov byte [rdi], 0 ; завершающий ноль
dec rdi
mov rbx, 10 ; делитель

convert_loop:
xor rdx, rdx
div rbx ; rax = частное, rdx = остаток
add dl, '0'
mov [rdi], dl
dec rdi
test rax, rax
jnz convert_loop

inc rdi ; rdi теперь указывает на начало строки
mov rsi, rdi

; Считаем длину строки
xor rcx, rcx
mov rdx, rsi
calc_len:
cmp byte [rdx], 0
je len_done
inc rdx
inc rcx
jmp calc_len

len_done:
mov [buf_len], rcx

; Выводим число
mov rcx, [stdout_handle]
mov rdx, rsi
mov r8, [buf_len]
mov r9, buf_len
mov qword [rsp + 32], 0
call [WriteConsoleA]

; Перевод строки
mov rcx, [stdout_handle]
mov rdx, newline
mov r8, 2
mov r9, buf_len
mov qword [rsp + 32], 0
call [WriteConsoleA]

; Завершение программы
xor ecx, ecx
call [ExitProcess]

print_zero:
mov qword [fib_num], 0
jmp convert_and_print

print_one:
mov qword [fib_num], 1
jmp convert_and_print

convert_and_print:
mov rax, [fib_num]
mov rdi, buffer + 31
mov byte [rdi], 0
dec rdi
mov rbx, 10

convert_loop2:
xor rdx, rdx
div rbx
add dl, '0'
mov [rdi], dl
dec rdi
test rax, rax
jnz convert_loop2

inc rdi
mov rsi, rdi

xor rcx, rcx
mov rdx, rsi
calc_len2:
cmp byte [rdx], 0
je len_done2
inc rdx
inc rcx
jmp calc_len2

len_done2:
mov [buf_len], rcx

mov rcx, [stdout_handle]
mov rdx, rsi
mov r8, [buf_len]
mov r9, buf_len
mov qword [rsp + 32], 0
call [WriteConsoleA]

mov rcx, [stdout_handle]
mov rdx, newline
mov r8, 2
mov r9, buf_len
mov qword [rsp + 32], 0
call [WriteConsoleA]

xor ecx, ecx
call [ExitProcess]

section '.idata' import data readable
library kernel32, 'kernel32.dll'

import kernel32, \
GetStdHandle, 'GetStdHandle', \
WriteConsoleA, 'WriteConsoleA', \
ExitProcess, 'ExitProcess'

Кстати, просьба: постить коды прямо здесь, под катом, ибо не по всем ссылкам могу проходить.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 10:02 
Для асм кода есть специальный вариант подсветки синтаксиса ASM, прям первым же в списке. Зачем прямым текстом то ... :facepalm:

-- 23.09.2025, 10:13 --

Код не то чтобы ужасен, но откровенно избыточен.
Например дважды преобразуют число в строку и выводят её! Зафига?! Бред, надо было или процедуркой, или просто переходом. Преобразование чисел 0 и 1 в строку тоже избыточно, можно было хранить готовые строки для этих случаев (или даже одну, в которую впечатывать нужное число двумя командами) и просто тупо их и выводить. Плюс отдельно вызывать WriteConsole для перевода строки излишество, надо было два байта добавить в буфер строки и выводить одним махом. Да и подсчитывать длину строки циклом по ней же нет нужды, можно вычесть указатель из начального значения.
Ну что цикл вычисления очередного числа можно сократить до
Используется синтаксис ASM
.fib:   xchg    rbx,rcx
        add     rcx,rbx
        dec     rdx
        jnz     .fib
это ладно, на скорость и объём кода практически не влияет.

-- 23.09.2025, 10:20 --

Ну а то что ИИ смог написать работающую прогу - не удивительно, тут же одни стандартные методы, ну кроме вычисления самого числа, которое люди писали миллион раз и в обучающей выборке ИИ оно встречалось множество раз, т.е. ИИ достаточно тупо скомпоновал стандартные (и известные ему) куски готового кода и совсем чуточку их соединил (условными) переходами.
Вот попросите его сгенерить код для чего-то ранее неизвестного ... Например пентадекатлона или поиска кортежей простых чисел по паттернам ... Ну-ну, хотел бы я посмотреть на результат. И на его скорость.
Да, обвязку (вывод чисел, преобразование числа в строку, работа с WinAPI) ИИ знает неплохо и может избавить от нудного набора кучи кода, но я бы всё равно за ним приглядывал, галлюцинации пока не отменили. Т.е. как помощник неплох, но своих знаний он пока не заменит.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 10:47 
Аватара пользователя
Dmitriy40 в сообщении #1702931 писал(а):
Для асм кода есть специальный вариант подсветки синтаксиса ASM,

Ну вот кое-кто у нас неоднократно про квадрат забывал, а я забыл про этот сервис :-)

Dmitriy40 в сообщении #1702931 писал(а):
Например пентадекатлона или поиска кортежей простых чисел по паттернам ... Ну-ну, хотел бы я посмотреть на результат.

Конечно это сделал. Попросил его найти тройки по 4 делителя. Уже до тысячи он ошибся — нашёл 14, хотя их 13. Но главное: его код у меня так и не заработал. Он правил его, правил, а ошибки всё появлялись.

После 5 раз надоело.

Ну вот одна из версий:

код: [ скачать ] [ спрятать ]
Используется синтаксис ASM
format PE64 console
entry start

include 'INCLUDE\win64axp.inc'

section '.data' data readable writable
    msg_intro db 'Triplets with exactly 4 divisors (up to 1000):', 13, 10, 0
    len_intro = $ - msg_intro

    buffer rb 64            ; буфер для чисел и строк
    buf_len dq 0

    comma_space db ', ', 0
    newline db 13, 10, 0
    total_msg db 'Total found: ', 0
    len_total = $ - total_msg

    stdout_handle dq ?
    triplet_count dq 0      ; счётчик найденных троек

section '.code' code readable executable
start:
    sub     rsp, 40
    mov     ecx, -11        ; STD_OUTPUT_HANDLE
    call    [GetStdHandle]
    mov     [stdout_handle], rax

    ; Вывод заголовка
    mov     rcx, [stdout_handle]
    mov     rdx, msg_intro
    mov     r8, len_intro
    mov     r9, buf_len
    mov     qword [rsp + 32], 0
    call    [WriteConsoleA]

    xor     r15, r15        ; n = 0 — текущее число
    xor     r14, r14        ; счётчик подряд идущих с 4 делителями
    xor     [triplet_count], rax  ; обнуляем счётчик троек

main_loop:
    inc     r15             ; n++

    ; Проверяем, если n > 1000 — выходим
    cmp     r15, 1000
    jg      print_total

    mov     rdi, r15
    call    count_divisors_optimized  ; в rax — количество делителей

    cmp     rax, 4
    je      has_four

    ; Не 4 делителя — сбрасываем счётчик подряд
    xor     r14, r14
    jmp     main_loop

has_four:
    inc     r14             ; увеличиваем счётчик подряд
    cmp     r14, 3
    jl      main_loop       ; если меньше 3 — продолжаем

    ; НАШЛИ ТРОЙКУ: n-2, n-1, n
    inc     qword [triplet_count]

    ; Выводим: (n-2), (n-1), (n)
    mov     rax, r15
    sub     rax, 2
    call    print_number
    mov     rdx, comma_space
    call    print_string

    mov     rax, r15
    sub     rax, 1
    call    print_number
    mov     rdx, comma_space
    call    print_string

    mov     rax, r15
    call    print_number
    mov     rdx, newline
    call    print_string

    ; ВАЖНО: не сбрасываем r14 полностью!
    ; Пример: 33,34,35,36 — если 36 тоже имеет 4 делителя,
    ; то 34,35,36 — тоже тройка!
    ; Поэтому сдвигаем "окно": считаем, что последние 2 числа всё ещё валидны.
    ; Но для простоты — просто сбросим и продолжим с n (текущего).
    ; Это безопасно, потому что если n+1 и n+2 тоже будут с 4 делителями —
    ; мы снова наберём 3 подряд.
    ; Альтернатива: r14 = 2 (если текущее число — третье в цепочке, то следующее может быть четвёртым — тогда тройка 2,3,4)
    ; Но для простоты и надёжности — сбросим и продолжим.
    ; → Сбрасываем, но оставляем текущее число как начало новой цепочки:
    mov     r14, 1          ; текущее число — уже одно в цепочке

    jmp     main_loop

print_total:
    ; Вывод "Total found: N"
    mov     rcx, [stdout_handle]
    mov     rdx, total_msg
    mov     r8, len_total
    mov     r9, buf_len
    mov     qword [rsp + 32], 0
    call    [WriteConsoleA]

    mov     rax, [triplet_count]
    call    print_number
    mov     rdx, newline
    call    print_string

    jmp     exit_program

exit_program:
    xor     ecx, ecx
    call    [ExitProcess]

; === ОПТИМИЗИРОВАННЫЙ ПОДСЧЁТ ДЕЛИТЕЛЕЙ ===
; Вход: rdi = n (n > 0)
; Выход: rax = количество делителей
count_divisors_optimized:
    push    rbx
    push    rcx
    push    rdx
    push    rsi

    mov     r9, 0           ; счётчик делителей
    mov     rbx, 1          ; d = 1
    mov     r8, rdi         ; сохраняем n

.loop:
    ; Проверка: если d * d > n — выходим
    mov     rax, rbx
    mul     rbx             ; rax = d * d
    cmp     rax, r8
    ja      .done           ; ← ЗДЕСЬ БЫЛО end_loop — ЗАМЕНИТЕ НА .done

    mov     rax, r8         ; n
    xor     rdx, rdx
    div     rbx             ; делим n на d → частное в rax, остаток в rdx

    test    rdx, rdx        ; остаток == 0?
    jnz     .next           ; если не делится — переходим к следующему d

    inc     r9              ; d — делитель, +1

    ; Проверяем, не является ли d квадратным корнем (d² == n)
    mov     rax, rbx
    mul     rbx
    cmp     rax, r8
    je      .next           ; если d² == n — не добавляем парный делитель

    inc     r9              ; иначе — добавляем парный делитель (n/d)

.next:
    inc     rbx
    jmp     .loop

.done:
    mov     rax, r9         ; возвращаем количество делителей
    pop     rsi
    pop     rdx
    pop     rcx
    pop     rbx
    ret

    ; Вычислим √n приблизительно — перебираем до rbx*rbx <= n
sqrt_loop:
    mov     rax, rbx
    mul     rbx             ; rax = rbx * rbx
    cmp     rax, r8
    jg      end_loop        ; если rbx² > n — выходим

    mov     rax, r8         ; n
    xor     rdx, rdx
    div     rbx             ; n / d

    test    rdx, rdx        ; остаток == 0?
    jnz     not_divisor

    ; rbx — делитель
    inc     rax             ; +1 делитель

    ; Если rbx * rbx != n, то есть и парный делитель: n / rbx
    mov     rax, rbx
    mul     rbx
    cmp     rax, r8
    je      not_double      ; если квадрат — не добавляем второй

    inc     rax             ; +1 за парный делитель
    jmp     not_double

not_divisor:
    xor     rax, rax        ; сброс, чтобы не мешало
not_double:
    ; Восстановим счётчик (rax был испорчен — сохраним отдельно)
    ; → лучше хранить счётчик в другом регистре
    ; Переделываем: храним счётчик в r9

    ; Исправленная версия:

    pop     rdi
    pop     rsi
    pop     rdx
    pop     rcx
    pop     rbx
    ; → Перепишем правильно:

    ; === Исправленная реализация ===
    push    rbx
    push    rcx
    push    rdx
    push    rsi
    push    rdi

    mov     r9, 0           ; счётчик делителей
    mov     rbx, 1          ; d = 1
    mov     r8, rdi         ; n

cd_loop:
    ; Проверяем: если d*d > n — выход
    mov     rax, rbx
    mul     rbx
    cmp     rax, r8
    ja      cd_done

    mov     rax, r8
    xor     rdx, rdx
    div     rbx             ; rax = n/d, rdx = остаток

    test    rdx, rdx
    jnz     cd_next

    ; rbx — делитель
    inc     r9

    ; Проверяем, не квадрат ли это
    mov     rax, rbx
    mul     rbx
    cmp     rax, r8
    je      cd_next         ; если d² == n — не добавляем парный

    inc     r9              ; иначе — добавляем парный делитель

cd_next:
    inc     rbx
    jmp     cd_loop

cd_done:
    mov     rax, r9         ; возвращаем результат
    pop     rdi
    pop     rsi
    pop     rdx
    pop     rcx
    pop     rbx
    ret

; === Вывод числа из rax ===
print_number:
    push    rax
    push    rbx
    push    rcx
    push    rdi
    push    rsi

    mov     rdi, buffer + 63
    mov     byte [rdi], 0
    dec     rdi
    mov     rbx, 10

pn_convert:
    xor     rdx, rdx
    div     rbx
    add     dl, '0'
    mov     [rdi], dl
    dec     rdi
    test    rax, rax
    jnz     pn_convert

    inc     rdi
    mov     rsi, rdi

    ; Считаем длину строки
    xor     rcx, rcx
    mov     rdx, rsi
pn_len_loop:
    cmp     byte [rdx], 0
    je      pn_print
    inc     rdx
    inc     rcx
    jmp     pn_len_loop

pn_print:
    mov     [buf_len], rcx
    mov     rcx, [stdout_handle]
    mov     rdx, rsi
    mov     r8, rcx
    mov     r9, buf_len
    mov     qword [rsp + 32], 0
    call    [WriteConsoleA]

    pop     rsi
    pop     rdi
    pop     rcx
    pop     rbx
    pop     rax
    ret

; === Вывод строки, на которую указывает rdx (с нулевым завершением) ===
print_string:
    push    rax
    push    rcx
    push    r8
    push    r9
    push    rdx

    ; Считаем длину строки
    xor     rcx, rcx
    mov     rax, rdx
str_len_loop:
    cmp     byte [rax], 0
    je      str_print
    inc     rax
    inc     rcx
    jmp     str_len_loop

str_print:
    mov     r8, rcx
    mov     rcx, [stdout_handle]
    pop     rdx
    mov     r9, buf_len
    mov     qword [rsp + 32], 0
    call    [WriteConsoleA]

    pop     r9
    pop     r8
    pop     rcx
    pop     rax
    ret

section '.idata' import data readable
    library kernel32, 'kernel32.dll'
    import kernel32, \
           GetStdHandle, 'GetStdHandle', \
           WriteConsoleA, 'WriteConsoleA', \
           ExitProcess, 'ExitProcess'

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 11:27 
Yadryara в сообщении #1702938 писал(а):
Но главное: его код у меня так и не заработал. Он правил его, правил, а ошибки всё появлялись.

У меня такая история бывает с pari/gp.
Но там я могу сам понять где проблема.
Часто банально не соблюдается баланс скобок.
Иногда ИИ придумывает несуществующие встроенные функции.
Иногда неправильно использует встроенные функции (неверные типы аргументов, например).
Если с 3-4 раза не исправилось, то как правило ошибка зацикливается. Тогда я сдаюсь и правлю код сам или делаю новый запрос с измененной формулировкой.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 11:45 
Аватара пользователя
wrest, мне конечно до Вас далеко в Паришном плане. Но как насчёт написать прогу по этой задачке? Для контроля: первая тройка начинается с 33, вторая — с 85...

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 12:10 
Чего её писать-то ... Вот, с первого раза, за полчаса максимум:
Код:
? b=n=0; for(x=2,1000, if(numdiv(x)==4, if(n==0, b=x); n++ , if(n>2, print(b,": ",vector(n,i,numdiv(b+i-1)),", len=",n)); n=0); );
33: [4, 4, 4], len=3
85: [4, 4, 4], len=3
93: [4, 4, 4], len=3
141: [4, 4, 4], len=3
201: [4, 4, 4], len=3
213: [4, 4, 4], len=3
217: [4, 4, 4], len=3
301: [4, 4, 4], len=3
393: [4, 4, 4], len=3
445: [4, 4, 4], len=3
633: [4, 4, 4], len=3
697: [4, 4, 4], len=3
921: [4, 4, 4], len=3

И на асм это можно перевести буквально "в уме", почти как и написано. Может не с первого раза заработает, но пары часов хватит. Больше мороки будет с выводом результатов. Ну и numdiv() придётся написать, ещё пара часов (можно использовать готовый кусок от ИИ, только проверить что работает правильно).
А уж на С это переписать вообще за часок можно. Без всякой мороки с выводом.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 13:09 
Yadryara в сообщении #1702947 писал(а):
Но как насчёт написать прогу по этой задачке?

Ну вот ув. Dmitriy40 уже написал. Но я например не понял какой "этой" :mrgreen:
В стартовом посте никакой задачи нет.
А... это про "полупростые": найти и напечатать первое из трех последовательных натуральных чисел с количеством делителей равным 4 (включая единицу и само число). Ну это да, скрипт one-liner.
Тут мы имеем дело всё с той же факторизацией, и оптимизации скажем так применимые к "общей задаче факторизации" наверное применимы и тут.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 14:17 
Аватара пользователя
wrest, вот эта задача:

Yadryara в сообщении #1702938 писал(а):
найти тройки по 4 делителя

Да, Дмитрий написал правильную прогу, только моя до 1e8 пока работает почти втрое быстрее. Вот чуть поправил вывод у Дмитрия:

Код:
{print();t0=getwalltime();
b=n=kpod=0;
for(x=2,10^8,
if(numdiv(x)==4,
if(n==0, b=x); n++ ,
if(n>2, kpod++); n=0); );
print(kpod);
print;print(strtime(getwalltime()-t0));print;
}quit;

103474

1min, 27,658 ms


А вот мой вывод:

Код:
<=10^8           26538772         6186940       1049769     717517           103474

30,698 ms

Ваше слово.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 14:24 
Yadryara в сообщении #1702961 писал(а):
Ваше слово.

Я ничего не понял :mrgreen:
Ваш код не запускается.
Что вы считаете до $10^8$ и почему результат состоит из 5 чисел?

У меня на планшете так:
Код:
? count_triples(1,10^8)
time = 1min, 29,397 ms.
%4 = 103474
?

Текст на pari/gp который запускается:
Код:
count_triples(a, b) = {
    my(count = 0);
    if(b - a < 2, return(0));
    for(n = a, b - 2,
         if(numdiv(n) == 4 && numdiv(n+1) == 4 && numdiv(n+2) == 4,
            count++;
        )
    );
    return(count);
}

Возвращает количество троек "полупростых" чисел в заданном диапазоне.
Условие if(numdiv(n) == 4 && numdiv(n+1) == 4 && numdiv(n+2) == 4 должно вычисляться последовательно, так что повторных вычислений не должно быть много (это если появляются четверки, пятерки и т.п. полупростых подряд). Оптимизаций ессно никаких нет.

------
Касательно ассемблера...
Муторное это дело. Муторность канеш в "обвязке" ввода-вывода, и вызова подпрограмм, в основном. Мне кажется, для этого давно придумали ассемблерные вставки в языках высокого уровня - и вам, в частности, как мне кажется, надо смотреть именно туда в поисках ускорения "тупых" вычислений. Насчёт более быстрого кода на ассемблере чем например на C -- ну не знаю, если речь о неограниченной разрядности то на ассемблере это опять же очень муторно будет. Если речь о 64 разрядах (ну или, если точнее, о разрядности регистров) - ну тогда норм.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 14:57 
Аватара пользователя
wrest в сообщении #1702962 писал(а):
Ваш код не запускается.

В смысле? :-) Я же не показывал пока свой код.

wrest в сообщении #1702962 писал(а):
Что вы считаете до $10^8$ и почему результат состоит из 5 чисел?

Я считаю количество троек и кое-что ещё. Может догадаетесь. А пока можете не обращать внимания на все числа кроме первого и последнего, которое как раз количество цепочек длиной 3 и совпадает с результатом Дмитрия, а также с A039833.

Пока что, увы — не вижу у Вас в проге ни интервала, ни количества цепочек, ни засечки времени...

Оптимизировать конечно есть что.

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 15:09 
Аватара пользователя
Я тоже попробую однострочник
Код:
(15:05) gp > for(i=1,249,k=4*i+1;if(numdiv(k)==4&&numdiv(k+1)==4&&numdiv(k+2)==4,print(k)))
33
85
93
141
201
213
217
301
393
445
633
697
921
(15:05) gp >

Разве тройка может иметь в себе число кратное 4?

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 15:13 
Вообще-то я за скоростью на PARI не гнался ...
Понятно что можно проверять на количество делителей лишь каждое третье число и только если подошло проверять и соседние. Это и даст ускорение почти втрое, 40с против исходных 1м48с.
Потом можно додуматься что центральное число чётное, это ускорит ещё вдвое.

А дальше можно включить голову и понять что центральное число обязано быть произведением двойки на простое, а значит перебирать можно циклом
forprime(p=3,1e8/2, numdiv(2*p-1)==4 && numdiv(2*p+1)==4 && kpod++; );
что даёт время 3.9с!
Вспомнив что из трёх чисел одно обязательно делится на 3, можно добавить проверку на простоту второго делителя:
forprime(p=3,1e8/2, isprime(round(2*p/3)) && numdiv(2*p-1)==4 && numdiv(2*p+1)==4 && kpod++; );
что ускоряет до 1.4с!

Достаточно ускорения?

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 15:24 
Dmitriy40 в сообщении #1702967 писал(а):
что даёт время 3.9с!

Вот! Голова нужна :!:

 
 
 
 Re: Как писать быстрые программы
Сообщение23.09.2025, 15:26 
Аватара пользователя
А можно кратко - что считаем?

 
 
 [ Сообщений: 63 ]  На страницу 1, 2, 3, 4, 5  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group