См. источник грани , который использует getBoundingClientRect . Это как:
function inViewport (el) {
var r, html;
if ( !el || 1 !== el.nodeType ) { return false; }
html = document.documentElement;
r = el.getBoundingClientRect();
return ( !!r
&& r.bottom >= 0
&& r.right >= 0
&& r.top <= html.clientHeight
&& r.left <= html.clientWidth
);
}
Возвращает true
, если какая-либо часть элемента находится в окне просмотра.
50!
- очень большое число (более 60 цифр), а 2^64
меньше 50!
. Причина, по которой вы не получаете правильное число, заключается в том, что вы получаете overflow , вы считаете выше предела того, что может вычислить ваш компьютер.
enter n 50
-3258495067890909184
Если у вас есть 64-разрядное целое число, наибольшее значение, которое оно может представлять, равно 2 ^ 64, для которого я меньше 50 !. Поэтому вы получаете переполнение.
Обычно в этих ситуациях вы прибегаете к некоторому трюку, похожим на 4-битную систему с 8-битным кодом, удваивая количество инструкций на слово (путь Intels first CPU имеет 8-битный код).
Таким образом, ваша 64-битная система может обрабатывать 128-битные слова, вам просто нужно написать алгоритм, который помещает данные в «куски», чтобы вы могли удвоить длину слова.
50!
- 30414093201713378043612608166064768844377641568960512000000000000
или около 3.04e+64
, 215-битное число. Это значение обычно превышает диапазон типов, например long
. Даже uintmax_t
и unsigned long long
необходимо только иметь возможность представлять по меньшей мере 64-битные целые числа.
long int fact(long int n) {
...
// Overflows!
return n*fact(n-1);
Чтобы получить точный ответ, код может использовать альтернативные типы. Следующее использует строковое / десятичное представление целого числа. Он работает при больших значениях n
, так как правильная функциональность ограничена размером буфера.
char *strfact_mult(char *s, unsigned x) {
unsigned sum = 0;
size_t len = strlen(s);
size_t i = len;
while (i > 0) {
sum += (s[--i] - '0')*x;
s[i] = sum%10 + '0';
sum /= 10;
}
while (sum) {
len++;
memmove(&s[1], s, len);
s[i] = sum%10 + '0';
sum /= 10;
}
return s;
}
char *str_fact(char *dest, unsigned n) {
strcpy(dest, "1");
while (n > 1) {
strfact_mult(dest, n--);
}
return dest;
}
int main(void) {
char buf[1000];
puts(str_fact(buf, 0));
puts(str_fact(buf, 1));
puts(str_fact(buf, 5));
puts(str_fact(buf, 50));
}
Выход
1
1
120
30414093201713378043612608166064768844377641568960512000000000000
Он не будет работать со стандартными типами C, вам нужно что-то еще (может быть, строка). Посмотрите на http://onlinemschool.com/math/formula/factorial_table/
Как видите, это довольно большое число.
/* program to calculate large factorials with exact precision
original program by chux, modified by ringzero
*/
#include <stdio.h>
#include <string.h>
char *strfact_mult(char *s, unsigned x)
{
// modified code starts
int len = strlen (s);
int carry = 0;
for ( int i = 1; i <= len; ++i ) {
int product = (s[len - i] - '0') * x + carry;
s[len - i] = product % 10 + '0';
carry = 0;
if ( product > 9 ) {
carry = product / 10;
if ( i == len ) {
++len;
memmove (&s[1], s, len);
s[0] = '0';
}
}
}
// modified code ends
//unsigned sum = 0;
//size_t len = strlen(s);
//size_t i = len;
//while (i > 0) {
// sum += (s[--i] - '0')*x;
// s[i] = sum%10 + '0';
// sum /= 10;
//}
//while (sum) {
// len++;
// memmove(&s[1], s, len);
// s[i] = sum%10 + '0';
// sum /= 10;
//}
return s;
}
char *str_fact(char *dest, unsigned n)
{
strcpy(dest, "1");
while (n > 1) {
strfact_mult(dest, n--);
}
return dest;
}
int main (void)
{
char buf[1000];
puts(str_fact(buf, 0));
puts(str_fact(buf, 1));
puts(str_fact(buf, 5));
puts(str_fact(buf, 50));
}