2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3  След.
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 18:11 


05/09/16
11533
guryev в сообщении #1331219 писал(а):
Переводим в double, извлекаем корень третьей степени, округляем его до ближайшего целого, возводим это целое в куб, сравниваем с исходным.

Это ме-е-е-е-дленно.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 18:13 
Заслуженный участник


16/02/13
4112
Владивосток
wrest в сообщении #1331218 писал(а):
Они должны быть взаимно-простыми?
Смотря для чего. Если только использовать остатки для проверки возможной кубичности — не обязательно, хотя процент выигрыша у взаимно простых повыше.

-- 09.08.2018, 01:14 --

wrest в сообщении #1331222 писал(а):
Это ме-е-е-е-дленно
Не факт. Стоит проверить.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 18:21 


05/09/16
11533
mihaild
Для n до 10^4 перебором нашлось n=9828 с максимальной "эффективностью": 31
Запустил перебор до 10^5, похоже это очень надолго, как вы нашли ваше 575757 - случайно набрали на клавиатуре?

-- 08.08.2018, 18:23 --

iifat в сообщении #1331224 писал(а):
Не факт. Стоит проверить.

У меня так примерно и работает сейчас. Я верю программистам PARI/GP и использую их встроенную функцию ispower которая как-то проверяет является ли число нужной степенью.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 18:26 
Заслуженный участник
Аватара пользователя


16/07/14
8465
Цюрих
Если $a = bc$, где $gcd(b, c) = 1$, то количество кубических вычетов по модулю $a$ равно произведению количеств кубических вычетов по модулям $b$ и $c$.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 18:46 
Заслуженный участник


20/08/14
11177
Россия, Москва
wrest
Ещё идейка по ускорению вычисления $\sqrt[3]{x}$. Ну таблицу кубов для всех интересующих $t$ уже посчитали заранее. Теперь считаем $a=\sqrt{x}$ (а он считается почти со скоростью деления), после чего двоичным поиском по таблице кубов ищем подходящее значение $t$ в диапазоне $(0,a=\sqrt{x})$. Для чисел $t\le10^4$ диапазон поиска миллион и достаточно всего 20 обращений в массив (или возведения в куб если памяти жалко). Это не так уж долго даже с умножениями без массива. Для $t\le10^n$ достаточно $5n$ возведений в куб.
И разумеется это делать лишь если проверка по модулю не отвергла $x$.
Вот будет забавно если ispower примерно так и действует ... :D

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 18:53 


05/09/16
11533
Dmitriy40 в сообщении #1331234 писал(а):
Ещё идейка по ускорению вычисления $\sqrt[3]{x}$.

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

Я тоже надеюсь, что ispower действует максимально эффективно, но вряд ли использует таблицы предвычисленных кубов или "хеши".

-- 08.08.2018, 19:45 --

Dmitriy40 в сообщении #1331234 писал(а):
И разумеется это делать лишь если проверка по модулю не отвергла $x$.

Да, как проверку-то делать?
Вот есть у меня число 90909 и есть вектор v в котором перечислены все возможные остатки от деления кубов на это число, их 1365.
Теперь берем какое-нибудь (проверяемое) число, делим его на 90909 с остатком и проверяем не получился ли какой-нибудь из этих 1365?

Делаем вектор со всеми кубическими вычетами по модулю: 90909
Код:
v=vector(90909,i,i^3%90909)

Оставляем в векторе только неповторяющиеся остатки:
Код:
v=vecsort(v,,8)

Заводим функцию, проверяющую на потенциальную кубичность:
Код:
iscube(n)=my(d=90909);r=n%d;if(vecsearch(v,r),return(1),return(0))

Смотрим примерно 10^7 проверок
Код:
? for(i=10^6,10^7,iscube(i))
  ***   last result computed in 6,335 ms.
? for(i=10^6,10^7,ispower(i,3))
  ***   last result computed in 1,107 ms.

Что-то не так...
Повышаем ставки:
Код:
? for(i=10^9,10^9+10^7,iscube(i))
? ##
  ***   last result computed in 7,051 ms.
?  for(i=10^9,10^9+10^7,ispower(i,3))
? ##
  ***   last result computed in 875 ms.

Все равно фигня.
Конструкция без вызова функции, а роверки прямо по месту улучшает в два раза но все равно работает долго:
Код:
? for(i=10^9,10^9+10^7,vecsearch(v,i%90909))
? ##
***   last result computed in 2,090 ms.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 20:00 
Заслуженный участник


20/08/14
11177
Россия, Москва
Я имел в виду что тоже может пользоваться двоичным поиском по аргументу возведения в степень, уж умножения достаточно быстры на современных процессорах.

(Оффтоп)

Но подумав ещё, думаю там всё же метод Ньютона, он быстрее должен сходиться. Проверка это не опровергает, для чисел до $2^{64}$ на x64 PARI ispower(x,3) выполняется за 700 тактов в среднем, что в начале, что в конце диапазона, что вполне похоже на полтора десятка делений.
Впрочем на битовое взвешивание с аккуратной реализацией даже больше похоже, как раз около 100 умножений по 5 тактов каждое плюс условие выбора бита. И удвоение времени при переходе границы $2^{64}$ тоже именно за это.


-- 08.08.2018, 20:07 --

wrest
Ну я же Вам процитировал практически готовый код (на С):
Dmitriy40 в сообщении #1331200 писал(а):
Там смысл в этих двух кусочках кода (привожу с сокращениями):
Используется синтаксис C++
//Заполнение массива флагов
const TInt CUBES_MOD = 575757;
std::vector<bool> cubesMod(CUBES_MOD, false);
for (t = 0; t < MAX_T; ++t) cubesMod[(t * t * t) % CUBES_MOD] = true;
//Использование массива флагов
if (!cubesMod[t_target % CUBES_MOD]) continue;//Такое t_target точно не является никаким кубом и извлекать корень не нужно
Т.е. словами, заполняем массив флагов так чтобы он по младшим цифрам числа указывал может ли куб какого-то числа иметь такие младшие цифры. Младшие цифры берутся не десятичные, а по модулю CUBES_MOD, при удачном выборе этого числа количество true в массиве будет сильно меньше количества false и для многих и многих t_target извлекать корень не понадобится.
Что тут непонятного? Объявляем массив длиной 575757, проходим по интересующим нас числам 0..MAX_T и расставляем в массиве флаг что число с таким остатком по модулю 575757 является кубом некоего числа. Это была инициализация.
При использовании вместо vecsearch просто обращаемся к массиву по индексу [x%CUBES_MOD] и если флаг сброшен, то не существует чисел, куб которых даёт такой остаток по данному модулю. Если же такие числа есть, то надо продолжить проверку и например тупо проверить ispower(x,3).

-- 08.08.2018, 20:27 --

Ну вот и PARI код для чисел до $10^4$ (лень ещё переменную вводить):
Код:
? MODS=575757;cubeMod=vector(MODS,i,false);for(i=0,10^4,cubeMod[i^3%MODS+1]=true);\\Инициализация
? for(i=10^10,10^10+10^7,if(cubeMod[i%MODS+1]==true,ispower(i,3)))
? ##
  ***   last result computed in 1,483 ms.
? for(i=10^10,10^10+10^7,if(true,ispower(i,3)))
? ##
  ***   last result computed in 905 ms.
Да, с массивом оказывается медленнее, значит ispower хорошо оптимизирована.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 20:28 
Заслуженный участник
Аватара пользователя


16/07/14
8465
Цюрих
iifat в сообщении #1331217 писал(а):
а в поле по модулю 575757 — в среднем 140
Это всё-таки не поле.
Ну и в среднем кубический корень имеет одно значение (т.к. возведение в куб - однозначная операция).

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 21:05 


05/09/16
11533
Dmitriy40 в сообщении #1331248 писал(а):
При использовании вместо vecsearch просто обращаемся к массиву по индексу [x%CUBES_MOD] и если флаг сброшен, то не существует чисел, куб которых даёт такой остаток по данному модулю.

А, то есть сначала все числа проверить на псевдокубовость и запомнить результат, а потом там рыться чтобы не делить с остатком...
Ну как-то оно не быстрее-то vecsearch вышло почему-то (а можете у себя с vecsearch) проверить?
Мне вот интересно, mihaild писал что у него проверка с 400 по 500 в пределах секунды. А у вас? Можете сравнить С++ а и PARI/GP?

Вот код на PARI/GP без предвычисления, для прохождения головоломки от 400 до 500

(Оффтоп)

Код:
k(z)=my(n=0,z5=z^5,xmax=sqrtnint(z5,4)+1,ymax=xmax,t=0);for(x=1,xmax,for(y=x,ymax,n=x^4+y^4;if(n>z5,next(2));if(ispower(z5-n,3,&t),print("x=",x," y=",y," z=",z," t=",t))))
for(i=400,500,k(t)

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 21:31 
Заслуженный участник


20/08/14
11177
Россия, Москва
wrest в сообщении #1331227 писал(а):
Для n до 10^4 перебором нашлось n=9828 с максимальной "эффективностью": 31
Ещё $n=15561$ даёт хорошую эффективность, всего $315$ вхождений, эффективность $49{,}4$. Предыдущее $n=14364$ давало эффективность лишь $32{,}6$. Код для поиска (выводит только при увеличении эффективности):
Код:
best=0;for(n=2,10^6,s=vector(n);for(i=0,#s-1,s[i^3%n+1]=1);w=vecsum(s);if(n/w>best,best=n/w;printf("n=%d / %d = %0.1f\n",n,w,best)))


-- 08.08.2018, 21:39 --

wrest в сообщении #1331262 писал(а):
(а можете у себя с vecsearch) проверить?
Могу:
Код:
? v=vector(90909,i,i^3%90909);v=vecsort(v,,8);iscube(n)=my(d=90909);r=n%d;if(vecsearch(v,r),return(1),return(0));
? for(i=10^6,10^7,iscube(i))
? ##
  ***   last result computed in 32,402 ms.
? for(i=10^6,10^7,ispower(i,3))
? ##
  ***   last result computed in 515 ms.
? for(i=10^9,10^9+10^7,iscube(i))
? ##
  ***   last result computed in 36,146 ms.
? for(i=10^9,10^9+10^7,ispower(i,3))
? ##
  ***   last result computed in 561 ms.
Почему у меня более 30с вместо 6-7с как у Вас я не знаю.
C++ код проверить не могу.

-- 08.08.2018, 21:44 --

wrest
Кстати, если будете делать с операцией % в индексе векторов PARI, имейте в виду что индекс векторов начинается с 1, а не с 0 как в С/С++, и программа может налететь на ошибку если получится нулевой остаток, именно поэтому я в коде делаю +1 индексу массива.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 21:40 


20/04/10
1776
В тестах простоты для определения является ли число полным квадратом сначала проверяют является ли оно квадратичным вычетом по нескольким небольшим простым модулям (благо - символ Лежандра вычислять довольно просто). Если число не является полным квадратом, тогда вероятность того, что оно пройдет $n$ таких проверок $1/2^n$.

По аналогии можно поступать и с определением является ли число кубом. Отличие от предложенного выше в том, что не потребуется создавать предварительно рассчитанные массивы в памяти. Выбираем простые вида $6k+1$, например набор $\{7, 13, 19, 31\}$. Для данного $x$ и каждого простого $p$ из выбранного набора проверяем является ли $x$ кубическим вычетом по модулю $p$. Поскольку удобной процедуры (типа вычисления символа Лежандра с использованием Закона квадратичной взаимности), по-моему, не известно, то проверяем в лоб $x^{\frac{p-1}{3}}\equiv1\pmod{p}$. Если число не куб, то вероятность, что $n$ проверок будут пройдены равна $1/3^n$.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 22:36 
Заслуженный участник


20/08/14
11177
Россия, Москва
Мне кажется одно деление и одно обращение в массив, причём если уж выдаёт ложь, то точно не куб - быстрее множества умножений по модулю.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 22:49 


20/04/10
1776
Это надо проверять. Не маленькая вероятность, что будет достаточно одной-двух проверок. Выше я не совсем аккуратно написал, что проверяем для всех простых из множества. Разумеется, если сравнение не выполнено для какого-то простого, то число кубом не является и его мучить не надо.

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение08.08.2018, 23:22 


05/09/16
11533
Dmitriy40
Кстати, у pari/gp открытый исходный код и можно же посмотреть где там ispower и как реализована, но я в этом не понимаю и найти не могу. Нашел файл с таки именем, но там текст из справки, которая выдается по ??ispower

 Профиль  
                  
 
 Re: Проверка что число - куб
Сообщение09.08.2018, 00:19 
Заслуженный участник


20/08/14
11177
Россия, Москва
И всё же метод с дополнительным массивом для проверки по остаткам имеет смысл. Написал примитивную (без особых оптимизаций) утилиту извлечения кубического корня для чисел до $2^{31}$ и сравнил её скорость без массива и с предварительной проверкой по массиву:
Код:
C:\TEMP>sqrt3.exe
n=15561 / 315 : 10780ms, 3994ms.
Это посчитаны кубические корни миллиарда чисел от одного до двух миллиардов. Т.е. 10 или 4 нс на число в среднем. Ускорения в 50 раз не видно, но в 2.5 раза есть. Думаю выигрыш съедается операцией деления, а 10-ти кратное битовое взвешивание с возведением в куб (всего 20 умножений) недостаточно долгое чтобы сильно перевесить деление.
PARI:
Код:
? for(i=10^9,2*10^9,ispower(i,3))
? ##
  ***   last result computed in 57,002 ms.


-- 09.08.2018, 00:32 --

Зато если резко замедлить вычисление корня (использовав int64 числа, x32 код работы с которыми после компилятора ужасен), то выигрыш от предпросмотра по массиву очень даже проявляется:
Код:
C:\TEMP>sqrt3.exe
n=15561 / 315 : 220726ms, 10593ms.
Условия те же, весь второй миллиард. Ускорение уже более 20 раз.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 44 ]  На страницу Пред.  1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group