Существует три основные причины.
FacesServlet
не вызывается. FacesServlet
mapping . URL-адрес ссылки (URL-адрес, который вы видите в адресной строке браузера) должен соответствовать
файла FacesServlet
, как определено в web.xml
чтобы все работы JSF выполнялись. FacesServlet
- это тот, который отвечает за разбор файла XHTML, сбор представленных значений формы, выполнение преобразования / проверки, обновление моделей, вызывание действий и создание выходных данных HTML. Если вы не вызываете FacesServlet
по URL-адресу, то все, что вы получили (и увидите через rightclick, View Source в браузере), действительно является исходным исходным кодом XHTML.
Если
, например, *.jsf
, ссылка должна указывать на /register.jsf
, а не на /register.xhtml
. Если это, например, /faces/*
, как и у вас, ссылка должна указывать на /faces/register.xhtml
, а не на /register.xhtml
. Один из способов избежать этой путаницы - просто изменить
с /faces/*
на *.xhtml
. Таким образом, нижестоящее является идеальным отображением:
facesServlet
javax.faces.webapp.FacesServlet
facesServlet
*.xhtml
Если вы по какой-то причине не можете поменять
на *.xhtml
, то вы, вероятно, также хотели бы, чтобы конечные пользователи не могли напрямую обращаться к источнику XHTML кодировать файлы по URL-адресу. В этом случае вы можете добавить
в
в *.xhtml
с пустым
в web.xml
, который предотвращает это:
Restrict direct access to XHTML files
XHTML files
*.xhtml
Предстоящий JSF 2.3 решит все из вышеперечисленного, автоматически регистрируя FacesServlet
в шаблоне URL-адреса *.xhtml
во время запуска webapp.
. С введением JSF 2.2 еще одна вероятная причина заключается в том, что пространства имен XML не соответствуют версии JSF. xmlns.jcp.org
, как показано ниже, является новым с JSF 2.2 и не работает в старых версиях JSF. Символы почти такие же, как если бы FacesServlet
не вызывался.
Если вы не можете перейти на JSF 2.2, вам нужно вместо этого использовать старые пространства имен java.sun.com
XML:
. Еще одна вероятная причина заключается в том, что несколько реализаций JSF были загружены вашим webapp, конфликтуя и разлагая друг друга. Например, когда ваш путь к классу среды выполнения Webapp загрязнен несколькими различными версиями JSF-библиотек или в конкретной комбинации Mojarra 2.x + Tomcat 8.x, когда в файле web.xml
веб-приложения есть ненужная запись ConfigureListener
, вызывающая ее загрузку дважды.
com.sun.faces.config.ConfigureListener
При использовании Maven убедитесь, что вы правильно определяете зависимости и понимаете области зависимостей. Важно: не связывайте зависимости в webapp, если они уже предоставлены целевым сервером.
JSF имеет очень крутую кривую обучения для тех, кто не знаком с базовыми HTTP , HTML и сервлетами . В Интернете много ресурсов низкого качества. Пожалуйста, игнорируйте фрагменты скриншотов кода, поддерживаемые любителями, в основном ориентированные на доход от рекламы, а не на обучение, такие как розы, учебник, javabeat и т. Д. Они легко узнаваемы, нарушая рекламные ссылки / баннеры. Также, пожалуйста, игнорируйте ресурсы, связанные с юрским JSF 1.x. Они легко узнаваемы с помощью JSP-файлов вместо файлов XHTML. JSP как технология просмотра устарела с тех пор, как JSF 2.0 уже в 2009 году.
Чтобы начать правильно, начните с нашей вики-страницы JSF и закажите авторитетную книгу .
Вы можете легко решить это, думая о проблеме в двоичном виде. Floor(3/2*i) - это, по сути, сдвиг вправо, усечение и сложение. В псевдокоде:
0b_n[0] = 10 // the start is 2
0b_n[1] = 10 + 1(0) = 11 // shift right, chop one bit off and add
0b_n[i+1] = 0b_n[i] + Truncate(ShiftRight(0b_n[i]))
Это должно быть довольно быстро реализовано в любой форме.
Я только что сделал реализацию этого в системе Mathematica, и кажется, что операция BitShiftRight также отрезает бит после единичной позиции, так что об этом заботятся автоматически. Вот одна строка:
In[1] := Timing[num = Nest[(BitShiftRight[#] + #) &, 2, 999999];]
Out[2] = {16.6022, Null}
16 секунд, число печатается просто отлично, хотя оно довольно длинное:
In[2] := IntegerLength[num]
Out[2] = 176092
In[3] := num
Out[3] = 1963756...123087
Полный результат здесь.
Вы почти нашли это. В следующий раз ознакомьтесь с онлайн-энциклопедией целочисленных рядов .
Вот запись: http://oeis.org/A061418
FORMULA
a(n) = ceiling[K*(3/2)^n] where K=1.08151366859...
The constant K is 2/3*K(3) (see A083286). - Ralf Stephan, May 29, 2003
Сказано:
>>> def f(n):
... K = 1.08151366859
... return int(ceil(K*(1.5)**n))
Тест на психическое здоровье:
>>> for x in range(1, 10):
... print f(x)
...
2
3
4
6
9
13
19
28
42
Круто! А как насчет 1000000:
>>> f(1000000)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 3, in f
OverflowError: (34, 'Result too large')
Ну, я попробовал. :]
Но вы поняли идею.
Редактировать еще раз: Решение найдено! См. Тимо или Лассе В. Карлсен .
Редактировать: Используя идею смещения битов Тимо:
import gmpy
n=gmpy.mpz(2)
for _ in xrange(10**6-1):
n+=n>>1
print(n)
дает
1963756763 ... 226123087 (176092 цифры)
% time test.py > test.out
real 0m21.735s
user 0m21.709s
sys 0m0.024s
Я использовал следующую Java-программу:
import java.math.*;
public class Series {
public static void main(String[] args) {
BigInteger num = BigInteger.valueOf(2);
final int N = 1000000;
long t = System.currentTimeMillis();
for (int i = 1; i < N; i++) {
num = num.shiftLeft(1).add(num).shiftRight(1);
}
System.out.println(System.currentTimeMillis() - t);
System.out.println(num);
}
}
Обрезанный вывод: ( полный вывод на pastebin )
516380 (milliseconds)
196375676351034182442....29226123087
Так что потребовалось около 8,5 минут на моей скромной машинке. Я использовал -Xmx128M
, но не уверен, действительно ли это было необходимо.
Вероятно, существуют лучшие алгоритмы, но это заняло в общей сложности 10 минут, включая написание простой реализации и запуск программы.
N=500
(согласно OEIS 061418 ) N=100K
(1445232038814....522773508
) Это почти повторение отношения первого порядка, за исключением пола, который запутывает вещи. Если вам не нужно слово,
http://en.wikipedia.org/wiki/Recurrence_relation
Кроме того, не используйте bash.
Причина того, что ваш скрипт такой медленный, заключается в том, что он запускается bc
трижды, tr
один раз и sed
один раз в цикле.
Перепишите все это в bc
и выполните sed
в конце. Мой тест показывает, что версия, предназначенная только для bc
, работает более чем в 600 раз быстрее. На старой медленной системе версии bc
потребовалось чуть менее 16 минут, чтобы найти 100 000-е значение (распечатывая только последнее).
Также обратите внимание, что ваша функция «floor» на самом деле является int.
#!/usr/bin/bc -lq
define int(n) {
auto oscale
oscale = scale
scale = 0
n = n/1
scale = oscale
return n
}
define series(n) {
return int(3/2*n)
}
n = 2
end = 1000
for (count = 1; count < end; count++ ) {
n = series(n)
}
print count, "\t", n, "\n"
quit
Обратите внимание, что print
является расширением, и некоторые версии bc
могут не иметь его. Если это так, просто укажите на переменную отдельно, и ее значение должно быть выведено.
Теперь вы можете выполнить chmod + x series.bc
и называть его так:
./series.bc | tr -d '\n' | sed 's.\\..g'
Это идентифицируется как последовательность A061418
в сайте последовательностей
(также известная как «Интернет-энциклопедия целочисленных последовательностей»); на соответствующую страницу ,
ФОРМУЛА
a (n) = A061419 (n) +1
=потолок [K * (3/2) ^ n]
гдеK = 1.08151366859
... Константа K равна2/3 * K (3)
(см. A083286).
и с подходящей высокоточной библиотекой (GMP, как уже предлагалось, или MPIR, и, возможно, оболочка сверху, как мой ребенок gmpy для Python), вы можете использовать формулу закрытой формы для многих более быстрое вычисление «миллионной позиции в серии» и тому подобное.
Часто можно поместить рекурсивно определенные рекурсии в замкнутые формулы. Конкретная математика (Грэхема, Кнута и Паташника) для обширного введения в этот предмет для новичков действительно трудно превзойти.
Хм, bash
не то, что я Буду использовать для высокоскоростной численной обработки. Получите себе копию GMP и соберите для этого программу на языке C.
Вполне возможно, что существует математическая формула, чтобы быстро ее дать, но за время, необходимое вам, чтобы это понять, GMP, вероятно, может выдать вам результат: -)
Вот версия на Python, которая на моем 10-летнем ноутбуке выполняется за 220 секунд:
import math;
import timeit;
def code():
n = 2
nth = 1
while nth < 1000000:
n = (n * 3) >> 1
nth = nth + 1
print(n);
t = timeit.Timer(setup="from __main__ import code", stmt="code()");
print(t.timeit(1));
Она дает тот же результат, что и этот ответ на pastebin (то есть я проверил начало и конец, а не все)
.Рекурсивная формулировка займет довольно много времени при большинстве Curcumstances, потому что он должен поддерживать стек машины. Почему бы не использовать динамический программирование вместо этого?
т.е. (псевдокод)
bignum x = 2
for (int i = 1; i < 1000000; i++) {
x = floor(3.0/2*x)
}
Конечно, для значимого результата вам понадобится высокоточная числовая библиотека.
Я преобразовал идеи Тимо в elisp. Ошибка 100, что дает отрицательное число. FAIL, см. no BigNums !
(progn
(let ((a 2)
(dummy 0))
(while (< dummy 100)
(setq a (+ a (lsh a -1)))
(setq dummy (1+ dummy)))
(message "%d" a)))
-211190189 #WRONG evalution
Вы, вероятно, сможете приблизиться немного ближе, используя более подходящий язык, например, Схема:
(define (series n) (if (= n 0) 2
(quotient (* 3 (series (- n 1))) 2)))
Это вычисляет 17610 цифр (серия 100000)
примерно за 8 секунд на моей машине. К сожалению, (series 1000000)
все еще занимает слишком много времени, чтобы даже гораздо более новая / более быстрая машина имела хоть какую-то надежду закончить за минуту.
Переход на C ++ с библиотекой для больших целых чисел (в данном случае NTL):
#include <NTL/zz.h>
#include <fstream>
#include <time.h>
#include <iostream>
int main(int argc, char **argv) {
NTL::ZZ sum;
clock_t start = clock();
for (int i=0; i<1000000; i++)
sum = (sum*3)/2;
clock_t finish = clock();
std::cout << "computation took: " << double(finish-start)/CLOCKS_PER_SEC << " seconds.\n";
std::ofstream out("series_out.txt");
out << sum;
return 0;
}
Это вычисляет ряд для 1000000 за 4 минуты 35 секунд на моей машине. Этого достаточно, чтобы я мог почти поверить, что действительно быстрая новая машина может хотя бы приблизиться к завершению за минуту (и да, я проверил, что произошло, когда я использовал сдвиги вместо умножения / деления - это был медленнее).
К сожалению, вычисление в закрытой форме, предложенное другими, похоже, мало помогает. Чтобы использовать его, вам нужно вычислить константу K с достаточной точностью. Я не вижу вычисления K в закрытой форме, поэтому на самом деле это просто сдвигает итерацию к вычислению K, и похоже, что вычисление K с достаточной точностью немного (если таковое имеется) быстрее, чем вычисление исходной серии.
Это очень просто сделать в Pari :
n=2;for(k=1,10^6,n+=n>>1)
Это займет 14 секунд на моей машине. Конечно, есть и более быстрые способы - на ум приходит GMP, - но зачем вообще? Вы не сможете сократить время выполнения более чем на 10 секунд, а время разработки будет порядка минут . :)
Второстепенный момент: в исходной формулировке неоднозначно, желателен ли миллионный член n 999999 или n 1000000 , число с индексом один миллион; Я даю последнее, так как вижу, что первое уже вычислено выше.