2015-03-20 1 views
3

OK, voici un puzzle de programmation/physique, disons Java (bien que ce ne soit pas vraiment important - mais par souci de cohérence, nous utiliserons Java).Calcul de la position, de la vélocité et d'autres dérivées d'un mouvement de manière efficace

J'ai un tableau de doubles où chaque élément représente les dérivées successives de la position d'un objet. Alors:

d[0] // position 
d[1] // velocity 
d[2] // accelleration 

etc ...

Il y aura au moins 1 et potentiellement un certain nombre d'éléments (mais dans la pratique, probablement pas plus de 5). Tous les éléments au-delà de la fin du tableau sont supposés être zéro. Nous avons également un double t pour le temps.

Donc, si d.length étaient 3 alors très précisément:

d[0] += d[1] * t + d[2] * t * t/2 
d[1] += d[2] * t 

Mais comment pouvons-nous écrire une solution itérative (pas récursion!) Qui mettra à jour tous les éléments du tableau pour l'instant t pour une durée de une?

Des votes devraient être accordés pour l'efficacité et la concision.

EDIT: Les lois du mouvement sont sur les pages de la physique de ce site, mais essentiellement chaque terme a la forme:

power(t,n)/factorial(n) 

Ainsi, le prochain mandat de la première équation serait d[3] * t*t*t/6

Si vous n'êtes pas familier avec ces équations, s'il vous plaît ne me demandez pas d'expliquer.

Un cas de test:

final static double[] D = { 5.0, 4.0, 3.0, 2.0, 1.0 }; 
double t = 10.0 

devrait donner:

[945.0, 300.66666666666663, 73.0, 12.0, 1.0] 

Le deuxième élément peut varier en raison d'erreurs de précision.

+0

S'il vous plaît, pouvez-vous mettre à jour votre question en montrant un exemple avec a.length == 3? – davidbuzatto

+0

Vous posez donc des questions sur un schéma d'intégration? avez-vous un pas de temps fixe? – MinaKamel

+0

Doit avoir été length == 3. Passez à d pour le nom du tableau afin de ne pas le confondre avec l'accélération. t n'est évidemment pas fixe. – rghome

Répondre

2

Je pense que quelque chose comme cela fonctionne.

int length = d.length; 
for (int i = 0; i < length - 1; i++) { 
    double temp = 0; 
    for (int j = length - 1; j > i; j--) 
     temp = (temp + d[j]) * t/(j - i); 
    d[i] += temp; 
} 
+0

Cela donne des erreurs d'arrondi légèrement moins bonnes que les autres solutions: [945.0, 300.66666666666674, 73.0, 12.0, 1.0] – rghome

+0

@rghome Il fera oui. La façon de calculer des puissances comme 't * t * t * t * t' est précisément d'utiliser' Math.pow' (car chaque multiplication successive introduit une autre erreur).Donc, si vous voulez une précision, vous ne pouvez pas réutiliser les réponses précédemment calculées pour 't',' t * t', 't * t * t',' t * t * t * t'. Si la précision est ce que vous voulez, je ne pense pas que vous pouvez faire mieux que de calculer chacun de «t», «t * t/2», «t * t * t/6» à partir de zéro, mais je pourrais me tromper. –

+0

J'ai obtenu des erreurs d'arrondi plus petites en faisant d'abord la division, mais cela dépendra peut-être du cas de test. – rghome

1

Mise à jour:

for (int i = 0; i < d.length - 1; i++) { 
    d[i] = 0; 
    int f = 1; 
    double p = 1; 
    for (int j = i+1; j < d.length; j++) { 
     f *= j - i; 
     p *= t; 
     d[i] += d[j] * p/f; 
    } 
} 
+0

Up-vote pour la première réponse, mais je pense qu'il devrait être possible d'éviter de recalculer la factorielle et la puissance dans la boucle interne au moins. Peut-être même dans la boucle extérieure. – rghome

+0

bon point, laissez-moi tenter le coup – axblount