Почему моя программа работает медленно?
Программа работает очень медленно особенно для земли и солнца, все время пишет один и тот же результат, есть возможность ее оптимизировать?
Задача : Сатурн и Земля находятся далеко от звезд, на них не действуют ни какие силы кроме силы притяжения. Через какое время Земля и Сатурн столкнутся если растояние между ними 1.2 * 10 ^9 км
код :
package ru.vassaev.mark;
import java.math.*;
class Body{
private float m1;
public float getM() {
return m1;
}
public void setM(float m1) {
this.m1 = m1;
}
float S(float m2,float R,float dt){
float G = (float) (6.67 * Math.pow(10,-11));
float a = (G * m2/((float)Math.pow(R,2)));
float S = ((a * dt * dt )/2);
return S;
}
}
public class CerezKakoeVremyaZemlyaUpadetNaSaturn {
public static void main(String[] args) {
Body Земля = new Body();
Земля.setM((float) (5.9736 * (float) Math.pow(10,24)));
Body Сатурн = new Body();
Сатурн.setM((float) (2 * Math.pow(10,26)));
float R = 150 * (float) Math.pow(10,9);
float dt = (float)0.001;
float t = 0;
while (R >= 0.001){
R = R - Земля.S(Сатурн.getM(),R,dt) - Сатурн.S(Земля.getM(),R,dt );
t+=dt;
System.out.println(R);
}
System.out.println(t);
}
}
А что Вы вообще делаете? Если надо найти время сближения Земли и Сатурна, импульсы которых в начальный момент времени считаются нулевыми, до момента их столкновения, то Ява Вам для этого совершенно не нужна - для этого достаточно решить задачу Коши для диффуравнения дистанции между планетами
d²r/dt²=-GM/r², r(0)=r₀, r'(0)=0, где r - дистанция между барицентрами планет, M - их совокупная масса, a G - универсальная гравитационная постоянная.
Так как уравнение явно не содержит времени t, его можно понизить на порядок, введя новую переменную v: v=dr/dt (v(0)=0).
Тогда d²r/dt²=dv/dt=dv/dr•dr/dt=v•dv/dr.
v•dv/dr = -GM/r².
Разделяем переменные: v•dv = -GMdr/r².
∫v•dv = -GM•∫dr/r²
v²/2 = GM/r - GM/r₀
v = dr/dt = ✓(2GM•(r₀-r)/(r₀r))
dr•✓((r₀r)/(2GM•(r₀-r))) = dt
T = ✓(r₀/(2GM))•∫(R;r₀)✓(r/(r₀-r))dr
R - совокупный радиус Земли и Сатурна.
T = ✓(r₀/(2GM))•(✓(R•(r₀-R))+r₀•arctg(r₀/R-1)).
Время T равно ≈236,3 года.
Если решать задачу Коши численно на ЭВМ, то вот пример полного исходника на "плюсах", по синтаксису достаточно схожих с Явой:
#include <cmath>
#include <iostream>
using namespace std;
int main()
{
double MEarth = 5.9742e24, REarth = 6.371e6,
MSaturn = 5.6851e26, RSaturn = 5.8232e7,
M = MEarth + MSaturn, R = REarth + RSaturn,
G = 6.6743e-11, dt = 86400., poldt = 0.5 * dt,
dtGM = dt * G * M, poldtGM = 0.5 * dtGM,
ae = 1.495978707e11, Year = 365.2422 * dt,
day = 0., r = 1.2e12, u = 0., dr, du, x;
cout << sqrt(r/2/G/M)*(sqrt(R*(r-R))+
r*atan(sqrt(r/R-1)))/Year << endl; cin >> x;
for (;;) { day += 1.; x = r+poldt*u; du = -dtGM/(x*x);
r += dt * (u-poldtGM/(r*r)); u += du; if (r < R) break;
cout << day << ") " << r/ae << ' ' << u << endl; }
cout << day / 365.2422;
}
Задача Коши для ОДУ тут решается модифицированным методом Эйлера. А Вы видите чему равен шаг по времени? Средним солнечным суткам, а не долям секунды! Поэтому Ольга Семёнова абсолютно права: избыточная точность - это и есть здесь главный тормоз! Можно сделать шаг по времени и ещё грубее (неделя, месяц, год) - ошибка во всех случаях получится вполне приемлемая.
Вывод расстояния (в астрономических единицах) и скорости (в м/с) происходит посуточно. Расстояние станет меньшим одной астрономической единицы на 84626-ые сутки от начала сближения (то есть через 231 год и 255 дней), а вообще время сближения составит где-то 86302 суток (236,29 года), причём в последние несколько суток будет мощный спурт, то есть сильное ускорение взаимосближения! Если вместо массы Сатурна подставить массу Солнца, а начальное расстояние сделать равным одной астрономической единице, тогда время сближения будет чуть больше двух месяцев - где-то на 65-ые сутки Земли уже не будет - его поглотит солнечная масса.
А у Вас я что-то вообще не вижу никакого нормального решения. И ответы типа "зачем тут цикл? в чём его смысл?", а также бредовую демагогию о миллиардах лет надо сразу дизлайкать, отправляя неучей в бан! Это то хоть понятно? У меня вот специально для Вас и формула для времени сближения планет выведена, и приведён элементарный пример численного решения Вашей задачи на ЭВМ, для которого спрашивать о смысле цикла и его пользе как-то нелепо да и просто глупо - это же совершенно ясно! Метод численного решения диффуравнения, если он чем-то не устраивает, можно поменять на другой, но это в принципе ничего не изменит - в лучшем случае результат получится несколько точнее да и всё.
Действительно, какой смысл в цикле?
У тебя же система простейших дифференциальных уравнений, которая, вероятнее всего, решается аналитически. И в полученную ручкой на бумаге формулу просто подставляем расстояния и массы планет.
Что касается твоего кода, то НИКОГДА не используй float - из-за этого ты получаешь слишком большую погрешность вычислений. Выбрось, на фиг, все (float) из кода и замени типы переменных с float на double.
джаву плющит от твоего кода...
есть какие-то идеи для оценки времени до столкновения? скажем так, если это миллиарды лет и ты по времени бежишь с интервалом одной миллисекунды... как долго это займёт? даже для программы...
и имеет ли смысл весь этот период перед столкновением?
Точность избыточна, это первое. Второе, можно заменить вычисление степеней десятки константами, просчитанными заранее на калькуляторе.
Критерий касания тоже непонятный: должна быть сумма радиусов тел, а там опять одна тысячная.
В общем, навести бы порядок в исходных данных: привести всё к метрам и секундам, как в международной системе единиц.
А цикл тут зачем?