| vasko.da.gamo |
03.12.2008 17:08 |
Помогите оптимизировать
Сделал программу для расчета числа линий по 1й формуле Эрланга: Формула для расчета
Дело в том, что при больших значениях нагрузки Y компьютер говорит, что ему не хватает памяти. Для расчетов используются такие числа как 10^1500 и больше. Я сделал так, что степень 10^X заносится в счетчик. Потому как в формуле мы делили бесконечность/бесконечность - получали мало.
Делаю с изменение шага (для оптимальности)
З.Ы. За синтакси пожалуйста не пинать...
Пример: Нагрузка Y=200 Эрл. Вероятность Р=0.005
Итоговое число линий - 227
[IMG]http://i019.***********/0812/ec/c4c90748adf3.jpg[/IMG]
Вот собственно код(можно просто вставить в фрейм и все)
Код AS1/AS2:
//Прогамма для расчета числа линий по 1й формуле Эрланга
var YM=[V];var YK=[V];//массивы для YM - чисел и YK - счетчиков
YM[0]=1;YK[0]=0;
Y = 200;//наша нагрузка
P = 0.005;//требуемая вероятность - стремимся к этому значению
E = 1;j = 1;//меряем шаги для оптимальности
VPer = Math.ceil(Y/2);
V=VPer;//VPer - для шага(меняем шаг, чтобы уменьшить число действий)
//будем выполнять до тех пор пока вероятность не будет меньше нашей
while (E>P) {
f = 0; V1 = 1; Y1 = 1;
//Далее следует функция для расчета числа V в степеени N
F1 = 0;//F1 -счетчик степеней для показательной функции в числителе
F2 = 0;//F2 - счетчик степеней для факториала
//если число на шаге i больше 10 то мы делим его на 1000 для надежности(чтобы число не превысило 10^300)
for (i=1; i<=V; i++) {
Y1 = Y*Y1;
if (Y1>10) {
Y1 = Y1/1000;
F1 = F1+1;
}
}
//Факториал V
for (w=1; w<=V; w++) {
V1 = V1*(f+1);
f = f+1;
if (V1>10) {
V1 = V1/1000;
F2 = F2+1;
}
}
B = Y1/V1;//Отношение верхней части дроби
F3 = F1-F2;//F3 - счетчик для числителя)
//производим суммирование от 0 до V,где V - число линий (нижняя часть дроби)
D = 0;//D - переменная для суммирования
for (i=1; i<=V; i++) {
Y2 = 1; F4 = 0;//F4 - счетчик степеней для показательной функции в знаменателе
for (m=1; m<=i; m++) {
Y2 = Y*Y2;
if (Y2>10) {
Y2 = Y2/1000;F4 = F4+1;}
;}
//расчеты для факториала в нижней дроби
S = 1; f = 0;
F5=0;//F5 - счетчик степеней для факториала в знаменателе
for (g=1; g<=i; g++) {
S = S*(f+1);
f = f+1;
if (S>10) {
S = S/1000;F5 = F5+1;}
;}
F6=F4-F5;T = Y2/S;
//Для дальнейших расчетов вносим число и счетчик его степени в массивы(каждый по отдельности)
YM[i]=T;YK[i]=F6;
}
//расчеты для суммирования закончены - результаты в МАССИВАХ!!!
Max=0;//ищем максимальную степень и вычитаем ее из всех степеней
for(i=0;i<=V;i++){if(YK[i]>Max){Max=YK[i];};}
for(i=0;i<=V;i++){D=D+YM[i]*Math.pow(1000,YK[i]-Max);}
F7=Max;//Делаем это для нашего удобства, чтобы не запутаться в переменных
E1 = B/D;//итоговая дробь
F8=F3-F7;//F8 - итоговая степень при 1000^X или 10^(3X)
E=E1*Math.pow(1000,F8);//наша вероятность (число F8 Не превышает 100)
//выводим результаты для поиска ошибок и сравнения
E2="шаг № "+j+":к-во линий="+V.toString()+";вероятность="+E.toString()+";отн.дроби="+E1.toString()+";сч.степеней="+F8.toString();
trace(E2);
VMax=V;
//Измением величину шага для оптимальности;
if(E<P and VPer>1){E=1;V = VMax-Math.ceil(VPer*0.5);VPer=Math.ceil(VPer/2);}
else{V = V+VPer;}
j=j+1;//считаем шаги дедовским способом
}
trace(V-1);//получим конечное число линий
Результаты трассировки:
Цитата:
шаг № 1:к-во линий=100;вероятность=0.504814362301093;отн.дроби=0.504814362301093;сч.степеней=0
шаг № 2:к-во линий=200;вероятность=0.0543524228386104;отн.дроби=0.0543524228386104;сч.степеней=0
шаг № 3:к-во линий=300;вероятность=9.21084077342936e-12;отн.дроби=9.21084077342936;сч.степеней=-4
шаг № 4:к-во линий=250;вероятность=0.000077471107936553;отн.дроби=0.077471107936553;сч.степеней=-1
шаг № 5:к-во линий=225;вероятность=0.00615719796255427;отн.дроби=6.15719796255427;сч.степеней=-1
шаг № 6:к-во линий=250;вероятность=0.000077471107936553;отн.дроби=0.077471107936553;сч.степеней=-1
шаг № 7:к-во линий=237;вероятность=0.00103072516893974;отн.дроби=1.03072516893974;сч.степеней=-1
шаг № 8:к-во линий=230;вероятность=0.00313135020914853;отн.дроби=0.00313135020914853;сч.степеней=0
шаг № 9:к-во линий=226;вероятность=0.00541931871187882;отн.дроби=0.00541931871187882;сч.степеней=0
шаг № 10:к-во линий=230;вероятность=0.00313135020914853;отн.дроби=0.00313135020914853;сч.степеней=0
шаг № 11:к-во линий=228;вероятность=0.00415115262004001;отн.дроби=4.15115262004001;сч.степеней=-1
шаг № 12:к-во линий=227;вероятность=0.00475204043193517;отн.дроби=4.75204043193517;сч.степеней=-1
227
|
Добавлено через 9 часов 13 минут
Хмм...один из выходов писать в AS3.(Только что узнал, что намного производительнее AS2)
Просто вставил код и мне выдает единственную ошибку:
Цитата:
1084: Syntax error: expecting rightparen before and.
с сылкй на строку
Код AS1/AS2:
if(VPer>1 and E<P){E=1;V = VMax-Math.ceil(VPer*0.5);VPer=Math.ceil(VPer/2);}
|
Вот сижу и думаю что не так... пока ничего не делал на AS3(никак перейти не могу)
Сделал в AS3
Код AS1/AS2:
//задаем типы переменных
var Y,P,i,w,j,f,F1,F2,F3,F4,F5,F6,Max,VMax,V,VPer:int;//счетчики
var YN,VN,B,D,T,E,E1:Number;//значения для расчета
var K,M:String;
var YM,YK:Array;
//Приступаем к решению
Y = 100;
P = 0.001;
E = 1;
j = 1;//меряем шаги для оптимальности
VPer = Math.ceil(Y/2);
V=VPer;//VPer - для шага(меняем шаг, чтобы уменьшить число действий)
while (E>P)
{
YN=1;
YM=[V];
YK=[V];
YM[0]=1;
YK[0]=0;
for (i=1; i<=V; i++)
{
YN = Y*YN;
if (YN>10)
{
YN = YN/1000;
F1 += 1;
}
}
//Факториал V
f = 0;
VN = 1;
for (i=1; i<=V; i++)
{
VN = VN*(f+1);
f += 1;
if (VN>10)
{
VN = VN/1000;
F2 += 1;
}
}
B = YN/VN;//Отношение верхней части дроби
F3 = F1-F2;//F3 - счетчик для числителя
//производим суммирование от 0 до V,где V - число линий (нижняя часть дроби)
D = 0;//D - переменная для суммирования
for (w=1; w<=V; w++)
{
YN = 1; F1 = 0;//F1 - счетчик степеней для показательной функции в знаменателе
for (i=1; i<=w; i++)
{
YN = Y*YN;
if (YN>10)
{
YN = YN/1000;
F1 += 1;
}
}
//расчеты для факториала в нижней дроби
f = 0;
VN = 1;
F2=0;//F2 - счетчик степеней для факториала в знаменателе
for (i=1; i<=w; i++)
{
VN = VN*(f+1);
f += 1;
if (VN>10)
{
VN = VN/1000;
F2 += 1;
}
}
F4=F1-F2;
T = YN/VN;
//Для дальнейших расчетов вносим число и счетчик его степени в массивы(каждый по отдельности)
YM[w]=T;
YK[w]=F4;
}
//расчеты для суммирования закончены - результаты в МАССИВАХ!!!
Max=0;//ищем максимальную степень и вычитаем ее из всех степеней
for(i=0;i<=V;i++)
{
if(YK[i]>Max)
{
Max=YK[i];
}
}
for(i=0;i<=V;i++)
{
D=D+YM[i]*Math.pow(1000,YK[i]-Max);
}
F5=Max;//Делаем это для нашего удобства, чтобы не запутаться в переменных
E1=B/D;//итоговая дробь
F6=F3-F5;//F6 - итоговая степень при 1000^X или 10^(3X)
E=E1*Math.pow(1000,F6);//наша вероятность (число F6 Не превышает 100)
//выводим результаты для поиска ошибок и сравнения
K="шаг № "+j+":к-во линий="+V.toString()+";вероятность="+E.toString()+";отн.дроби="+E1.toString()+";сч.степеней="+F6.toString();
trace(K);
VMax=V;
//Измением величину шага для оптимальности;
if(E<P && VPer>1)
{
E=1;
V = VMax-Math.ceil(VPer*0.5);
VPer=Math.ceil(VPer/2);
}
else
{
V = V+VPer;
}
j=j+1;//считаем шаги дедовским способом
}
trace(V-1);//Полученное число линий
|