2013-03-31 4 views
0

Я пишу программу, которая считывает данные длины волны и интенсивности из отдельных сигнальных и фоновых файлов (поэтому каждый файл состоит из нескольких пар длины волны и интенсивности). Как вы можете видеть, я делаю это, создавая структуру, а затем присваивая значения соответствующим элементам структуры, используя fscanf в цикле. Как только данные будут считаны, предполагается, что программа рассчитана на интервал, где записанные длины волн в каждом файле перекрываются, то есть общий диапазон длин волн. Длины волн идеально выравниваются там, где это перекрытие существует и, как известно, разнесены с постоянной разницей. Таким образом, мой способ определить, какие элементы массива структуры были применимы, заключался в том, чтобы определить, какая из минимальных длин волн двух файлов была выше, а максимальная длина волны была ниже. Затем, для файла с минимальным и более высоким максимумом, я бы нашел разницу между этим и более высоким минимумом/меньшим максимумом, а затем разделил его на постоянный шаг, чтобы определить, сколько элементов будет смещено. Это работает, кроме случаев, когда математика выполнена, программа возвращает неверный ответ, который совершенно необъяснимо.Необъяснимая вычислительная ошибка

В приведенном ниже коде я определяю постоянный шаг как lambdastep путем вычисления разницы между длинами волн одного элемента и элемента перед ним. С моими примерными данными это .002, что подтверждается printf. Однако, когда я запускаю программу и делясь на lambdastep, я получаю неправильный ответ. Когда я запускаю программу, делящую на .002, я получаю правильный ответ. Почему этот случай? Я не могу объяснить.

#include<stdio.h> 
#include<math.h> 
#include<stdlib.h> 
#include "plots.h" 

struct spectrum{ 
    double lambda; 
    double intensity; 
}; 

main(){ 
double a=0,b=0,c=0,d=0,lambdastep,smin,smax,bmin,bmax,tmin,tmax,sintmin,bintmin,tintmin,sintmax,bintmax,tintmax,ymin,ymax; 
int ns,nb,nt,i=0,sminel,smaxel,bminel,bmaxel,tminel,tmaxel; 
double min(struct spectrum *a,int,int); 
double max(struct spectrum *a,int,int); 
FILE *Input;         
Input = fopen("sig.dat","r"); 
FILE *InputII;        
InputII = fopen("bck.dat","r"); 
fscanf(Input,"%d",&ns); 
fscanf(InputII,"%d",&nb); 
struct spectrum signal[ns]; 
struct spectrum background[nb]; 
struct spectrum *s = &signal[0]; 
struct spectrum *ba = &background[0]; 
s = malloc(ns*sizeof(struct spectrum)); 
ba = malloc(nb*sizeof(struct spectrum)); 
while(fscanf(Input,"%lf%lf",&a,&b) != EOF){ 
    signal[i].lambda = a; 
    signal[i].intensity = b; 
    i++; 
} 
i = 0; 
while(fscanf(InputII,"%lf%lf",&c,&d) != EOF){ 
    background[i].lambda = c; 
    background[i].intensity = d; 
    i++; 
} 
for (i=0; i < ns ;i++){ 
    printf("%.7lf %.7lf\n", signal[i].lambda,signal[i].intensity); 
} 
printf("\n"); 
for (i=0; i < nb ;i++){ 
    printf("%.7lf %.7lf\n", background[i].lambda,background[i].intensity); 
} 
lambdastep = signal[1].lambda - signal[0].lambda;   //this is where I define lambdastep as the interval between two measurements 
smin = signal[0].lambda; 
smax = signal[ns-1].lambda; 
bmin = background[0].lambda; 
bmax = background[nb-1].lambda; 
if (smin > bmin) 
    tmin = smin; 
else 
    tmin = bmin; 
if (smax > bmax) 
    tmax = bmax; 
else 
    tmax = smax; 
printf("%lf %lf %lf %lf %lf %lf %lf\n",lambdastep,smin,smax,bmin,bmax,tmin,tmax); //here is where I confirm that it is .002, which is the expected value 
sminel = (tmin-smin)/(lambdastep); //sminel should be 27, but it returns 26 when lamdastep is used. it works right when .002 is directly entered , but not with lambdastep, even though i already confirmed they are exactly the same. why? 
+0

Можете ли вы изолировать его от простого деления двух чисел? Какие два номера? – nneonneo

ответ

1

sminel является целым числом, поэтому (tmin-smin)/lambdastep будет выдаваться на целое число при завершении вычисления.

Очень небольшое различие в lambdastep может быть разницей между получением, например, 27.00001 и 26.99999; последний усекает до 26 при приведении к int.

Попробуйте использовать floor, ceil или round, чтобы лучше контролировать округление возвращаемого значения.

+0

Ах, поскольку цифры в файле данных были точными, я упустил возможность lambdastep быть чем угодно, кроме .002. Я использовал round(), и программа теперь работает правильно. Спасибо вам за помощь. –

0

Это почти наверняка связано с присущей неточности вычислений с плавающей запятой. Пытаясь распечатать lambdastep со многими значимыми цифрами - держу пари, вы обнаружите, что его точное значение немного больше, чем вы думаете.

С моими данными образца, это .002, что подтверждено printf.

Попробуйте распечатать (lambdastep == .002).

Смежные вопросы