2016-11-25 17 views
0

Я пытаюсь рассчитать распределение Максвелла-Больцмана, но этот код дает 0.00000, в чем проблема?Расчет распределения Максвелла-Больцмана

#include<stdio.h> 
#include<stdlib.h> 
#include<math.h> 
int main() 
{ 

    float e=2.718228183, pi=3.14159265, m=2.66*pow(10,-23), t, k=1.38*pow(10,-23), v, result; 

    scanf("%f %f", &t, &v); 

    result = sqrt(pow(m/(2*pi*k*t), 3)) * 4 * pi * pow(v,2) * pow(e, -(m * pow(v,2))/(2*k*t)); 

    printf("%f", result); 
} 
+4

Код дает '0.000000' для * каких * входных значений? –

+0

теперь дает только 0 @SvenMarnach – user6200763

+0

например 500 100 @WeatherVane – user6200763

ответ

2

Как описан в комментариях, использование float вместе с пониженной точностью констант дает результат, который не представим больше как float. Изменение типа данных в двойном режиме дает две десятичные цифры точности. Если мы используем exp, больше цифр для pi и немного рекомбинации вычислений получаем 12 цифр точности. Например .:

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
int main() 
{ 

    double pi = 3.1415926535897932384626433832795028842, m = 2.66e-23, k = 
     1.38e-23; 
    double t, v, v2, dkt, result; 
    // check omitted 
    scanf("%lf %lf", &t, &v); 

    v2 = v * v; 
    dkt = 2 * k * t; 

    result = pow(m/(pi * dkt), 3/2.0) * 4 * pi * v2 * exp(-(m * v2)/(dkt)); 
    printf("%.20g\n", result); 
    return 0; 
} 

Результат от Pari/GP является 8.1246636077915008261803395870165527173e-9 и результат мы получаем с кодом выше 8.1246636077914841125e-09. Без промежуточных результатов v2, dkt и с заменой sqrt мы получили 8.1246636077914824582e-09, но это не значительная разница, особенно с точностью, где она ничего не получила.

Если вам нужны полные 16 десятичных цифр точности, вам нужно разобрать все это и принять другой подход.

+0

Реальное исправление в вашем коде случайно. С 'printf ("% e ", result);', код OP вычисляет '8.127763e-09'. Другие изменения в основном пух ... – EOF

+0

@EOF код выше не предназначен как исправление, о чем свидетельствует последнее предложение. По крайней мере, я думал, что это - последнее предложение - сможет дать понять, что немедленного решения нет, только с совершенно другим подходом. Двойной двойной (112-битный double-double) может сделать это для некоторого ограниченного, но, вероятно, достаточно большого диапазона, но я не сделал полного анализа вычисления. «Exp» и 'pow (x, y)' (= 'exp (y log x)') предполагали бы серию и минимаксную поли, найденную с Remez или аналогичной (например, с помощью http: // lolengine .net/вики/ОСС/lolremez). – deamentiaemundi

+0

Ошибка OP - это, вероятно, * не то, что n-я десятичная цифра неверна. Проблема OP заключалась в том, что результат был абсолютно бесполезным из-за идиотизма '% f' как спецификатора' printf() '-conversion. – EOF

0

заменить

double pi=acos(-1.); 

вместо

double pi=3.1415926535897932384626433832795028842;