Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> тяжелые вычисления 
:(
    Опции темы
cru3l
Дата 7.11.2009, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 7.8.2008

Репутация: нет
Всего: нет



есть такой скрипт

Код

function loadpage(){
var aNumbers=new Array();
var bNumbers=new Array();
var cNumbers=new Array();
var dNumbers=new Array();
var x,y,a,b,c,d,i,j,k,z;



for (i=0;i<100;i++)
{
aNumbers[i]=i;
bNumbers[i]=i;
cNumbers[i]=i;
dNumbers[i]=i;
}


x=78.578;



for (i=0;i<100;i+0.00001)
{
    for (j=0;j<100;j+0.00001)
    {
        for (k=0;k<100;k+00001)
        {
            for (z=0;z<100;z+00001)
            {
            
                
                var firstpart=(aNumbers[i]+bNumbers[j]);
                var secondpart=(cNumbers[k]+dNumbers[z]);
                var y=(aNumbers[i]/bNumbers[j])*(cNumbers[k]/dNumbers[z]);
                
                if (firstpart>72&&secondpart>72){                
                    
                    if (x==y)
                    {
                        document.write('x='+aNumbers[i]+'/'+bNumbers[j]+'*'+cNumbers[k]+'/'+dNumbers[z]+'<br>');
                    }
                
                }
            
            }
            
        }
    
    }

}

}



выполняется ооооочень долго (я так и не дождался, пришлось тестировать с цифрами меньше) и вешает браузер, что впрочем не удивительно. Как можно это все оптимизировать? Потоков вроде бы в яваскрипте нет, как с этим борятся люди?


PM MAIL   Вверх
bars80080
Дата 7.11.2009, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 15
Всего: 315



если бы вы описали реальную задачу, то можно было бы предложить более-менее оптимальное решение

а с вашим кодом борются очень просто - не пишут его
PM MAIL WWW   Вверх
Itsys
Дата 7.11.2009, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 12
Всего: 34



Мне интересно, какой результат Вы ожидаете для
Код

aNumbers[0.00001]

Может в приращении цикла всетаки ошибка?

Да и вообще странный алгоритм, для получения результата совершенно не обязательно перебирать все возможные значения.

Но для полного понимания, всетаки необходимо видеть исходную задачу
PM MAIL WWW Skype   Вверх
sTa1kEr
Дата 7.11.2009, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: нет
Всего: 146



Цитата(Itsys @  7.11.2009,  22:57 Найти цитируемый пост)
Может в приращении цикла всетаки ошибка?

А там нету вообще никакого приращения smile 
Цитата(cru3l @  7.11.2009,  19:34 Найти цитируемый пост)
for (i=0;i<100;i+0.00001)


PM MAIL   Вверх
cru3l
Дата 8.11.2009, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 7.8.2008

Репутация: нет
Всего: нет



да напортачил я там с этими +0.00001.

вот задача,

есть такое выражение

a/b * c/d = x

где, x — входные данные

и есть массив чисел например (20,20,20,21,35,36,40,50,70,85,90,88) — каждое значение можно использовать только один раз

a,b,c,d — это подобранные числа из массива, таким образом чтобы выражение было правильным, если конечно это возможно. 
И есть условие a+b>72 ; c+d>72

можно упростить формулу до a/b=x  (т.е. представить что c=1 и d=1) если решить задачу можно только таким образом 

x может быть не целым, например "78.875"


я в коде в качестве массива чисел просто забил массив значениями от нуля до ста (для примера). Ну и я не придумал ничего лучше кроме как "скопировать" массив 4 раза и перебирать все возможные варианты. Там в коде еще не учтено чтобы каждое значение можно было использовать один раз.

Ну что, можно такое сделать на яваскрипте, чтобы быстро работало?

Это сообщение отредактировал(а) cru3l - 8.11.2009, 17:19
PM MAIL   Вверх
cru3l
Дата 9.11.2009, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 7.8.2008

Репутация: нет
Всего: нет



ну что, такое задание остудило ваш пыл?  smile 

скажите хотя бы, такое вообще резонно делать на javascript'e, может все таки использовать что-нибудь более нативное для ОС
PM MAIL   Вверх
brother79
Дата 9.11.2009, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 471
Регистрация: 18.8.2009

Репутация: 1
Всего: 6



Цитата(cru3l @  9.11.2009,  12:32 Найти цитируемый пост)
ну что, такое задание остудило ваш пыл?  smile 

скажите хотя бы, такое вообще резонно делать на javascript'e, может все таки использовать что-нибудь более нативное для ОС 



Какие пределы по исходным данным? Просто мне пока только перебор с отсечением приходит в голову.


--------------------
PM MAIL WWW   Вверх
sTa1kEr
Дата 9.11.2009, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: нет
Всего: 146



Решение перебором (с учетом условия уникальности значений):
Код

var numbers = new Array(20,20,20,21,35,36,40,50,70,85,90,88);
var x = 9.894179894179896 // (88/21) * (85/36) == 9.894179894179896
var m = [0,0,0,0], k = 72;

// Для сравнения вещественных чисел с точностью до 3 знаков после запятой
x = Math.round(x * 1000);

function calculate(n) {
    if (n == 4) {
        if ( (m[0] + m[1]) > k && (m[2] + m[3]) > k ) {

            // Сообственно сама формула
            y = (m[0] / m[1]) * (m[2] / m[3]);

            if (Math.round(y * 1000) == x ) {
                document.write('x = ' + m[0] + '/' + m[1] + ' * ' + m[2] + '/' + m[3] + '<br />');
            }
        }
        return;
    }

    var len = numbers.length;
    for (var i = 0; i < len; i++) {
        m[n] = numbers.shift();
        calculate(n + 1);
        numbers.push(m[n]);
    }
}

calculate(0);

Вывод:
Код

x = 85/21 * 88/36
x = 85/36 * 88/21
x = 88/21 * 85/36
x = 88/36 * 85/21


Profile (115.684ms, 13346 calls)
Function   Calls    Percent  Own Time     Time         Avg          Mi           Max          File
calculate  13345    99.85%   115.511ms    115.511ms    0.009ms      0m           115.511ms    4 (line 9)
eval()     1        0.15%    0.173ms      117.765ms    117.765ms    117.765ms    117.765ms    4 (line 1)

PM MAIL   Вверх
cru3l
Дата 9.11.2009, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 7.8.2008

Репутация: нет
Всего: нет



sTa1kEr, спасибо за решение, работает действительно офигенно. но вот если подставить входной массив с такими данными

Код

var numbers = new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100);


то на выходе получаем опять ужасные тормоза. What's the trick?


PM MAIL   Вверх
cru3l
Дата 9.11.2009, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 7.8.2008

Репутация: нет
Всего: нет



и да, опять же — я как бы и не против таких тормозов. Но как сделать так, чтобы браузер при этом не зависал намертво. Просто вывести надпись - "Идет расчет" и считать себе спокойно как бы в отдельном треде.
время рассчета не сильно критично (в разумных пределах, конечно)
PM MAIL   Вверх
sTa1kEr
Дата 9.11.2009, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: нет
Всего: 146



Цитата(cru3l @  9.11.2009,  17:02 Найти цитируемый пост)
то на выходе получаем опять ужасные тормоза. What's the trick?

Логично, что для большего количества значений такой алгоритм не подойдет.
PM MAIL   Вверх
cru3l
Дата 9.11.2009, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 7.8.2008

Репутация: нет
Всего: нет



sTa1kEr, эх, мне бы до 100 включительно ((
PM MAIL   Вверх
sTa1kEr
Дата 9.11.2009, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: нет
Всего: 146



Цитата(cru3l @  9.11.2009,  17:24 Найти цитируемый пост)
ремя рассчета не сильно критично (в разумных пределах, конечно) 

Ну если несколько сотен часов - это разумный предел...

Для такого количества значений нужен другой алгоритм... надо будет подумать.
PM MAIL   Вверх
sTa1kEr
Дата 9.11.2009, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: нет
Всего: 146



Слегка улучшенный алгоритм все того же перебора (при большом значении k сильно уменьшает количество итераций):
Код

var numbers = new Array();
var a = numbers, b = numbers, c = numbers, d = numbers;
var x = 9.894179894179896 // (88/21) * (85/36)= 9.894179894179896
var m = [0,0,0,0], k = 72;

for (var i = 1; i <= 100; i++) {
    numbers.push(i);
}

// Для сравнения вещественных чисел с точностью до 3 знаков после запятой
x = Math.round(x * 1000);

function calculate(n) {
    if ((n + 1) % 2 == 0 && (m[n-1] + m[n]) <= k) {
        return;
    }

    var len = numbers.length;
    for (var i = 0; i < len; i++) {
        m[n] = numbers.shift();
        if (n == 3) {
            // Сообственно сама формула
            var y = (m[0] / m[1]) * (m[2] / m[3]);

            if (Math.round(y * 1000) == x ) {
                console.log('x = ' + m[0] + '/' + m[1] + ' * ' + m[2] + '/' + m[3]);
            }
        } else {
            calculate(n + 1);
        }
        numbers.push(m[n]);
    }
}

calculate(0);


Profile (115.684ms, 13346 calls)
Function    Calls   Percent Own Time    Time        Avg     Min Max         File
calculate   274529  100%    52749.617ms 53553.856ms 0.195ms 0ms 53553.856ms 24 (line 14)


Что-же касается фонового выполнения расчета, то для этого можно воспользоваться хаком с таймером, как описано здесь.
PM MAIL   Вверх
cru3l
Дата 9.11.2009, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 7.8.2008

Репутация: нет
Всего: нет



k можно было и не делать переменной. Оно всегда будет равно 72м. 

Алгоритм очень клевый. Работает быстро. Спасибо  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0569 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.