2013-02-08 5 views
1

У меня есть переменная типа const int, но параметры, от которых она зависит, имеют тип double. Когда я пытаюсь отбросить это от «double» до «const int», он работает неправильно. Например, когда N должно быть 991, оно вводится как 990. Я пробовал несколько методов, и только один работал, но я не уверен, будет ли этот метод работать все время. Вот некоторые методы, которые я пытался:C++ Тип casting от double до const int не работает должным образом

Первый метод:

const int N = (Ls-1)/dx + 1; 

Второй метод:

const int N = static_cast<const int>((Ls-1)/dx) + 1; 

Третий метод:

double Z = (Ls-1)/dx + 1; 
const int N = Z; 

Четвертый метод (только метод работы) :

double Z = (Ls-1)/dx; 
const int N = Z + 1; 

Обратите внимание, что dx - это такое значение, что остаток (Ls-1)/dx всегда будет равен нулю (т.е. это всегда целочисленное значение). В любом случае, объясните, почему другие методы не работают, чтобы я мог лучше понять, как отличить литье?

EDIT: В соответствии с просьбой, я загрузив весь код, чтобы показать, как все работает:

#include <iostream> 
#include <math.h> 
#include <stdio.h> 
#include <fstream> 
#include <cmath> 
#include <algorithm> 

#define pi 3.14159265 

using namespace std; 

//Define Fluid Properties 
double rho_L = 998; //Liquid Density 
double rho_LG = 828.9; //Liquid-Gas Density Ratio 
double mu_L = 0.000798; //Liquid Viscosity 
double mu_LG = 40.24; //Liquid-Gas Viscosity Ratio 
double sigma = 0.0712; //Surface Tension 
double nu_G = (mu_L/mu_LG)/(rho_L/rho_LG); 

//Define Injector Properties 
double Uinj = 56.7; //Injection Velocity 
double Dinj = 0.0998; //Injector Diameter 
double theta = 15.0*pi/180.0; //Spray Cone Angle 
double L = 500.0*Dinj; //Atomization Length 
double Ls = L/Dinj; //Normalized Atomization Length 

//Define Solver Parameters 
double K = 5294; //Viscous Dissipation Coefficient 
double Eps = pow(10,-5); //Residual Error 
double dx = 0.0001; //Step Size 
double Ui = 10; //Initial Guess 
//const int Z = static_cast<const int>((Ls-1)/dx + 1) + 1; 
const int N = (Ls-1)/dx + 1;//Z; 

double deriv (double U, double X, double delta, double m) 
{ 
    double dudx; 
    dudx = -(1.0/delta)*(1.0/U)*(U - sqrt(1.0 - U)/sqrt(m*X*X))*(U - sqrt(1.0 - U)/sqrt(m*X*X)); 
    return (dudx); 
} 

int main() 
{ 
    //Declare Variables 
    int max_step; 
    double ERR; 
    int step; 
    double DEN; 
    double SMD; 
    double m; 
    double Ug; 
    double Re; 
    double Cd; 
    double delta; 
    double K1; 
    double K2; 
    double K3; 
    double K4; 

    //Allocate Memory From Heap 
    double *U = new double [N]; 
    double *X = new double [N]; 

    //Initialize Vectors and Variables 
    DEN = 0.5*rho_L - (4.0/3.0)*K*(mu_L)/(Uinj*Dinj*Dinj)*L; 

    m = 4.0/rho_LG*tan(theta)*tan(theta); 

    for (int i = 0; i < N; i++) 
    { 
     X[i] = 1.0 + dx*i; 
    } 
    U[0] = 1.0; 

    max_step = 1; 
    ERR = 1; 
    step = 0; 
    while(abs(ERR) > Eps && step < max_step) 
    { 

     //Calculate Ug 
     Ug = sqrt(1.0 - (Ui/Uinj))/sqrt(m*Ls*Ls)*Uinj; 

     //Calculate SMD 
     SMD = 6.0*sigma/(DEN*(Uinj*Uinj - Ui*Ui)); 

     //Calculate Re # and Drag Coefficient 
     Re = abs(Ui-Ug)*SMD/nu_G; 

     if(Re <= 0.01) 
     { 
      Cd = (0.1875) + (24.0/Re); 
     } 
     else if(Re > 0.01 && Re <= 260.0) 
     { 
      Cd = (24.0/Re)*(1.0 + 0.1315*pow(Re,(0.32 - 0.05*log10(Re)))); 
     } 
     else 
     { 
      Cd = (24.0/Re)*(1.0 + 0.1935*pow(Re,0.6305)); 
     } 

     //Determine New U 
     delta = (4.0/3.0)*(1.0/Cd)*(rho_LG)*(SMD/Dinj); 

     //RK4 
     for (int i = 0; i < N-1; i++) 
     { 
      K1 = deriv(U[i],X[i],delta,m); 
      K2 = deriv(U[i]+0.5*dx*K1,X[i]+0.5*dx,delta,m); 
      K3 = deriv(U[i]+0.5*dx*K2,X[i]+0.5*dx,delta,m); 
      K4 = deriv(U[i]+dx*K3,X[i+1],delta,m); 
      U[i+1] = U[i] + dx/6.0*(K1 + 2.0*K2 + 2.0*K3 + K4); 
      //if(i >= 0 && i <= 3) 
       //cout << i << " " << K1 << " " << K2 << " " << K3 << " " << K4 << " " << U[i] << endl; 
     } 

     ERR = abs(U[N-1]*Uinj - Ui)/Ui; 

     Ui = U[N-1]*Uinj; 

     step = step + 1; 
    } 

    SMD = 6.0*sigma/(DEN*(Uinj*Uinj - Ui*Ui)); 

    cout << "U = " << Ui << endl; 
    cout << "SMD = " << SMD << endl; 
    cout << "DEN = " << DEN << endl; 
    cout << "Ug = " << Ug << endl; 
    cout << "m = " << m << endl; 
    cout << "delta = " << delta << endl; 
    cout << "Re = " << Re << endl; 
    cout << "Cd = " << Cd << endl; 
    cout << "U* = " << U[N-1] << endl; 
    cout << "Error = " << ERR << endl; 
    cout << "step = " << step << endl; 

    //Output Data Into Text File 
    ofstream outputdata("result-500-15.txt"); 
    for (int i = 0; i < N; i++) 
    { 
     outputdata << X[i] << " " << U[i] << '\n'; 
    } 
    outputdata.close(); 

    delete [] U; 
    delete [] X; 

    return 0; 
} 
+5

это звучит, как это может быть округление вопрос - возможно, '(Ls-1)/dx' фактически (скажем) +990,999999999999 , так что это эффективно 991, но downcasting усекает его до 990. Что произойдет, если вы попробуете 'static_cast ((Ls-1)/dx + 0.01) + 1'? – ruakh

+0

В настоящее время dx = 0,1 и Ls-1 = 99, поэтому (Ls-1)/dx должно быть 990, но, возможно, оно не может сделать 0,1 в двоичном формате? Если я добавлю 0.01, это сработает, но будет ли оно всегда? – user1562781

+0

На самом деле, теперь, когда я думаю об этом, округление не должно быть проблемой, потому что включение «+1» должно исправить любые проблемы округления. – user1562781

ответ

3

Ваше предположение верно: 0,1 не имеет конечное выражение в двоичной системе. Это довольно сложная проблема и имеет много угловых шкафов, которые не будут решены вообще, добавив 0,01, как указано в вашем комментарии. (Это сильно зависит от ожидаемых значений и т. Д.)

Ваш вопрос предполагает, что фактор всегда должен быть целым числом. В этом случае правильный подход для поддержания правильных результатов - не использовать double s для начала (для Ls, dx, Z). Либо используйте дробный тип (ничего не встроенный в C++, не используйте свою собственную или библиотеку), десятичный тип с произвольной точностью (опять же используйте библиотеку, например gmp - разумно, если вы знаете, что все ваши номера имеют конечное десятичное выражение) или, что самое простое: Если оба значения Ls и dx должны быть не более n цифр после десятичной точки, умножьте их на 10^n и используйте интегральные типы.


Хорошо, ваш код сильно отличается от того, что я ожидал. В этом случае, на мой взгляд, правильно, чтобы зафиксировать число шагов N и вычислить dx от этого, а не наоборот:

const int N = 10000; 
double dx = (Ls-1.0)/(double)(N-1); 

Если вы хотите начать со значением для йх и выберите N такое, что расчетное значение для йх, попросите пользователя при запуске программы:

#include <cmath> 

double dxestim; 
cout << "dx should be close to: "; 
cin >> dxestim; 
cout << "Candidate values for N: " << endl; 
int N1 = (int) floor((Ls-1)/dx + 1.0); 
int N2 = (int) ceil((Ls-1)/dx + 1.0); 
cout << N1 << " gives dx = " << (Ls-1.0)/(double)(N1-1) << endl; 
cout << N2 << " gives dx = " << (Ls-1.0)/(double)(N2-1) << endl; 
cout << "Please choose N: "; 
cin >> N; 
... 
+0

((Ls-1)/dx + 1) дает длину массива от конечной точки (Ls) до начальной точки (1), где (dx) - расстояние между каждым элементом. Я выбираю (dx) таким образом, что ((Ls-1)/dx + 1) всегда целое число, но, к сожалению, я должен иметь (Ls) и (dx) как двойные, потому что они используются в другом месте в код. Или лучше, чтобы я обновил их с явным типом кастинга позже? – user1562781

+0

Хммм. Трудно сказать, не видя большой картины, мне непонятно, должны ли они удваиваться или нет. Учитывая ваше описание, как вы выбираете 'dx', чтобы частное было целым числом? Мне кажется, что для этого требуется знание того, каким должно быть целое число, поэтому вы можете сохранить его в этот момент. – us2012

+0

Это математический решатель, поэтому dx необходимо изменить, чтобы решение было стабильным. Я выбираю его таким образом, чтобы (Ls-1)/dx всегда было целым числом. Я точно знаю, что значение N должно быть заранее, но я хотел бы сделать это автоматически, так что мне не нужно вводить его вручную при каждом изменении dx. Я могу загрузить весь код, если он объяснит все лучше. – user1562781