Triangular number rozwiązanie równania

0

Witam

mam do rozwiązania zadanie
Triangular number jest liczbą punktów, która może wypełnić trójkąt równoboczny. Np liczba 6 jest taką liczbą bo trójkat zbudowany z takiej liczby punktów jest równoboczny. Ogólnie problem sprowadza się do rozwiązania równania T(n) = n * (n + 1) / 2, gdzie T(n) jest daną szukaną zaś jest n. Poniżej moje rozwiązanie:

#include <stdbool.h>

bool is_triangular(int t) {
unsigned long long int delta = 1+8*t;
double x1=(-1-sqrt(delta))/2.0;
  if(x1>0&&floor(x1)==x1)
    return true;  
double x2=(-1+sqrt(delta))/2.0;
    if(x2>0&&floor(x2)==x2)
      return true;
return false;
}

Program przechodzi wszystkie test a wykrzacza mi się na t == 458000245 i t == 1979494660
Nie wiem gdzie jest bład

1

Czyli mamy funkcje f(x) = 1/2 * x^2 +1/2 * x - t i szukamy dla niej miejsca zerowego.
delta = b^2 - 4ac = 1/4 + 4*1/2*T(n) = 1/4 + 2*T(n)
Skąd u ciebie delta=1+8*t to nie wiem.

0

@gonskabalbinka:
Musisz policzyć pierwiastek całkowity z 1 + 8*Tn, z założenia istnieje, więc pierwiastek z delty znajdujesz:

unsigned long long sqrt_delta(unsigned long long n) {
    return   (unsigned long long) sqrt(1 + 8 * n);
}

W ten sposób double jest zamkniete w funkcji, a resztę robisz na inegerach.
Edycja: Wtedy rozwiąznie:

unsigned long long solution(unsigned long long n) {
    return (-1 + sqrt_delta(n)) / 2;
}

https://www.wolframalpha.com/input/?i=1979494660+triangular+number

0
gonskabalbinka napisał(a):
double x1=(-1-sqrt(delta))/2.0;
  if(x1>0&&floor(x1)==x1)

Wynik funkcji sqrt(delta) zawsze będzie dodatni.
Stad -1-sqrt(delta) zawsze będzie ujemne.
Proszę o wytłumaczenie czemu się spodziewasz że x1>0 może być prawdą?

Poza tym nie należy się spodziewać że wyrażenie floor(x1)==x1 będzie prawdą w związku z niedokładnością obliczeń.

0
unsigned long long int delta=0.25+0.5*t; // (1/4 + 2*t)/4
double x=sqrt(delta)-0.5;
0

Niedokładności w IEEE 754.

Bardzo często pomijane przez programistów, a przy dużych liczbach wyraźnie widoczne, bo cyfry znaczące kończą się już przed przecinkiem...

Łatwo sprawdzić w językach, które pozwalają na całkowicie dokładnie obliczenia na dowolnie dużych liczbach całkowitych (jak Python czy Haskell). Na przykład, wziąłem Twoje t == 458000245 i w Pythonie dostaję coś takiego:

>>> 458000245**2 == 458000245.0**2
False
>>> 458000245**2
209764224420060025
>>> 458000245.0**2
2.0976422442006003e+17

Więc tego rodzaju programy nie mają szans działać dokładnie dla dużych liczb jeśli robisz jakiekolwiek obliczenia w IEEE 754. Jak to mówią: "Komputer nie nadaje się do obliczeń". :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1