Come gestire grandi esponenti b di funzioni esponenziali, e ^ b?

0

Sto lavorando su un piccolo progetto (in un linguaggio molto "di basso livello" con un float a 32 bit a precisione singola che quasi non ha alcuna funzionalità oltre alle condizioni e ai loop di base) e ad un certo punto devo risolvere un sistema lineare di equazioni (4x4 o talvolta 5x5). Questo non è il problema, io uso l'algoritmo GAUSSian con pivoting. Per aumentare la velocità di calcolo, è anche possibile utilizzare una soluzione esplicita codificata diretta del sistema 4x4 (ad esempio ottenuta dalla cassetta degli attrezzi simbolica di Matlabs.)

Il problema che ho a che fare ora è che a volte nel mio sistema di equazioni possono verificarsi funzioni esponenziali e b con abbastanza alto esponenti, diciamo b > 10000 ... il fatto è che questi enormi valori svaniscono quando il sistema viene risolto. La prossima cosa è che b non sono valori interi ma alcune cose decimali ...

C'è un modo per un rapido tipo di "fattorizzazione" di ad esempio e 13421.1234 ? O cosa posso fare per rendere il mio sistema di equazioni risolvibile?

Modifica: esempio di equazioni

x_i = 0 ... >1000               = values from Measurement, i.e. time in days]
y_i = 0, 1e-6 ... 1e-4          = values from Measurement, i.e. creep-strain]
b_i = 1/1, 1/10, 1/100, 1/1000  = constants
a_i = Regression-Parameters to be estimated

(1): ( a_1*sum_{i=1}^{k}*e^{x_i*(b_1+b_1)} +
       a_2*sum_{i=1}^{k}*e^{x_i*(b_2+b_1)} +
       a_3*sum_{i=1}^{k}*e^{x_i*(b_3+b_1)} +
       a_4*sum_{i=1}^{k}*e^{x_i*(b_4+b_1)} ) = ( sum_{i=1}^{k} y_i*e^{x_i*b_1} )

(2): ( a_1*sum_{i=1}^{k}*e^{x_i*(b_1+b_2)} +
       a_2*sum_{i=1}^{k}*e^{x_i*(b_2+b_2)} +
       a_3*sum_{i=1}^{k}*e^{x_i*(b_3+b_2)} +
       a_4*sum_{i=1}^{k}*e^{x_i*(b_4+b_2)} ) = ( sum_{i=1}^{k} y_i*e^{x_i*b_2} )

(3): ( a_1*sum_{i=1}^{k}*e^{x_i*(b_1+b_3)} +
       a_2*sum_{i=1}^{k}*e^{x_i*(b_2+b_3)} +
       a_3*sum_{i=1}^{k}*e^{x_i*(b_3+b_3)} +
       a_4*sum_{i=1}^{k}*e^{x_i*(b_4+b_3)} ) = ( sum_{i=1}^{k} y_i*e^{x_i*b_3} )

(4): ( a_1*sum_{i=1}^{k}*e^{x_i*(b_1+b_4)} +
       a_2*sum_{i=1}^{k}*e^{x_i*(b_2+b_4)} +
       a_3*sum_{i=1}^{k}*e^{x_i*(b_3+b_4)} +
       a_4*sum_{i=1}^{k}*e^{x_i*(b_4+b_4)} ) = ( sum_{i=1}^{k} y_i*e^{x_i*b_4} )
    
posta Questionmarkengineer 21.08.2017 - 23:26
fonte

2 risposte

2

Quindi queste sono quattro o cinque equazioni lineari (in quattro o cinque incognite) con i tuoi $ e ^ b $ 's come coefficienti, giusto?

Quindi penso che puoi dividere tutti i termini di un'equazione con qualsiasi costante che ti piace. E ogni equazione ha quattro o cinque $ e ^ {b_i}, i = 1 ... 4 o 5 $ coefficienti. Quindi cerca solo il più piccolo $ b_i $ (in ciascuna equazione separatamente) e sottrai da ciascuno, cioè $ b_i - > b_i-b_ {min} $ in questa equazione. Fatelo separatamente per ogni equazione, e dovrebbe lasciare la soluzione generale invariata.

Siccome tu dici "questi enormi valori svaniscono quando il sistema è risolto", ciò implica che $ b_max-b_min $ non può mai essere molto grande. Quindi, quando sottrai i $ b_min $, questo dovrebbe lasciare il rimanente $ e ^ {b_i-b_min} $ trattabile.

    
risposta data 22.08.2017 - 01:33
fonte
0

Questa risposta SO ha un codice C per l'implementazione di pow e exp .

Se vuoi implementarlo tu stesso, ricorda che exp(a + b) = exp(a) + exp(b) (matematicamente, almeno). Se si dispone di un numero in virgola mobile, è possibile considerarlo come la somma di una parte intera e una parte decimale, x = n + d . exp(n) può essere calcolato con moltiplicazione ripetuta, e quindi devi solo trovare exp(d) .

Con una serie di Taylor intorno a 0 (tecnicamente una serie Maclaurin (:), che può essere calcolata come d + (d^2 / 2) + (d^3 / 6) + ... + (d^k / k!) . Dal momento che questi poteri sono tutti interi, possono essere calcolati con ripetute moltiplicazioni.

Prendi i risultati dalle due parti sopra, moltiplicali e hai exp(x) .

Non mi piace l'idea di moltiplicare ripetutamente e , ma potresti implementare l'esponenziazione di base 2 e calcolare exp(x) = 2^(x / log_2(e)) . Le potenze di interi di 2 possono essere calcolate con il bitshifting, ma la serie di Taylor per la parte decimale sarebbe disattivata. Non sono sicuro che sarebbe più preciso nel complesso.

Tieni presente che ci sono potenziali problemi di analisi numerica qui, specialmente con numeri negativi. Non penso che ci sarebbero problemi, ma raccomanderei test approfonditi del tuo algoritmo prima di usarlo in produzione. Le cose specifiche a cui prestare attenzione sono quanto lontano vuoi prendere la serie di Taylor, basi negative ed esponenti, e combinazioni di valori molto piccoli e molto grandi.

    
risposta data 22.08.2017 - 20:41
fonte

Leggi altre domande sui tag