C ++ Birçok sabitle, bilimsel kodlardaki değişkenlerle başa çıkmak için en iyi uygulamalar


17

Akışta bulunan biyolojik maddelerle akışkan akışını simüle etmek için bir kod geliştiriyorum. Bu, bazı ilave biyolojik modellere bağlı standart Navier-Stokes denklemlerini içerir. Birçok parametre / sabit vardır.

Büyük hesaplamaları işlemek için yazılı işlevlerim var, ama yaşadığım bir sorun bu hesaplamaların bağlı olduğu sabitlerin / parametrelerin çok sayıda. Bir işleve 10-20 argüman iletmek hantal görünüyor.

Bir alternatif, tüm sabitleri global değişkenler yapmaktır, ancak bunun C ++ 'da kaşlarını çattığını biliyorum.

Bir işleve birçok girişi işlemenin standart yolu nedir? Bunun için bir yapı oluşturmalı mıyım?

teşekkür ederim


7
Mümkünse, constexpr kullanarak sabitleri derleme zamanında değerlendirmeyi deneyin. Bunların çoğunu ayrı bir başlık dosyasına dahil etmeye çalışıyorum. Değişkenler için, ayrı bir sınıfın faydaları olduğunu buldum, ancak işleve geçmeden önce sınıfı başlatmak zorunda olduğunuz için potansiyel olarak daha fazla hata pahasına.
Biswajit Banerjee

3
Bu, bir tür kod örneği olmadan düzgün bir şekilde cevaplamak zordur. Bunun için bir yapı oluşturmalı mıyım? Genel olarak, evet, bu kesinlikle normal bir yol. Parametreleri / sabitleri anlamlarına göre gruplandırın.
Kirill

1
"Bir alternatif tüm sabitleri küresel değişkenler yapmak, ama biliyorum ki bu C ++ kaşlarını çattı" Değil mi?
Monica ile

1
Gerçekten, gerçekten sabit mi? Modelinizi farklı bir alana uygulamak isterseniz ne olur? Onları küçük bir sınıfa koymanızı tavsiye ederim. Bu en azından gelecekte size biraz esneklik sağlıyor
André

@ André Çoğu kullanıcı bir parametre dosyası ile kullanıcı tarafından kontrol edilir, bu yüzden sınıf çözüm en iyi olduğunu kabul ediyorum.
EternusVia

Yanıtlar:


13

Çalıştırmadan önce değişmeyecek sabitleriniz varsa, bunları bir başlık dosyasında bildirin:

//constants.hpp
#ifndef PROJECT_NAME_constants_hpp
#define PROJECT_NAME_constants_hpp
namespace constants {
  constexpr double G        = 6.67408e-11;
  constexpr double M_EARTH  = 5.972e24;
  constexpr double GM_EARTH = G*M_EARTH; 
}
#endif

//main.cpp
using namespace constants;
auto f_earth = GM_EARTH*m/r/r;  //Good
auto f_earth = G*M_EARTH*m/r/r; //Also good: compiler probably does math here too

Bunu yapmak istemenizin nedeni, derleyicinin çalışma zamanından önce sabit değerleri hesaplamasına izin vermesidir, bu da birçoğunuz varsa iyidir.

Değerleri iletmek için basit bir sınıf da kullanabilirsiniz:

class Params {
 public:
  double a,b,c,d;
  Params(std::string config_file_name){
    //Load configuration here
  }
};

void Foo(const Params &params) {
  ...
}

int main(int argc, char **argv){
  Params params(argv[1]);
  Foo(params);
}

Tüm harika cevaplar ama sınıf çözümü benim durumum için en iyi sonucu verir.
EternusVia

8
Değişkenleri global yaparsanız constexpr, en azından bunları namespacebaşka bir küresel simgeye basmamaları için bir içine alın . Adlı global bir değişkeni kullanmak Gsadece sorun çıkarmayı gerektirir.
Wolfgang Bangerth

1
Neden _ olan muhafızları yönlendiriyorsunuz? Asla _ ile başlayan bir şey yazmamalısınız, derleyici değişkenleri ile çarpışma riski vardır. Böyle bir şey yapmalısın ifndef PROJECT_NAME_FILE_NAME_EXTENSION. Ayrıca, neden sabitleri büyük harfle yazdığınızdan emin değilsiniz, ancak koruma makrolarınızı içermiyorsunuz. Genelde tüm makroları büyük harfle kullanmak istersiniz, özellikle de hijyenik olmadıkları için. Sabitler için kapitalizasyon genel olarak anlamlı değildir . GSI olduğundan iyidir, ancak mass_earth daha uygundur ve global yani anlamı için bir ad alanı ile nitelenmelidir constants::mass_earth.
whn

12

Düşüncelerinizle aynı doğrultuda olabilecek başka bir alternatif de sabitleri düzgün bir şekilde gruplandırmak için bir ad alanı (veya iç içe ad alanları) kullanmaktır. Bir örnek şunlar olabilir:

namespace constants {
   namespace earth {
      constexpr double G = 6.67408e-11;
      constexpr double Mass_Earth = 5.972e24;
      constexpr double GM = G*Mass_Earth;
   }// constant properties about Earth

   namespace fluid {
      constexpr double density = 0.999; // g/cm^3
      constexpr double dyn_viscosity = 1.6735; //mPa * s
   }// constants about fluid at 2C

   // ... 

} // end namespace for constants

Yukarıdaki tekniği kullanarak, referans sabitleri istenen bazı dosyalara ve ad alanlarına yerelleştirerek benzer avantajlardan bazılarını alırken küresel değişkenlerden daha kontrollü hale getirebilirsiniz. Sabitleri kullandığınızda, yapmak kadar basittir:

constexpr double G_times_2 = 2.0*constants::earth::G;

İç içe geçmiş ad alanlarının uzun zincirlerinden hoşlanmıyorsanız, gerektiğinde bir ad alanı takma adı kullanarak her zaman kısaltabilirsiniz:

namespace const_earth = constants::earth;
constexpr double G_times_2 = 2.0*const_earth::G;

2
Bu, OpenFOAM'ın izlediği bir yaklaşımdır ve OpenFOAM'ın kaynak kodunun rastgele bir örneğine bakın . OpenFOAM, akışkan dinamiğinde yaygın olarak kullanılan sonlu hacim yöntemini uygulayan C ++ kod kütüphanesidir.
Dohn Joe

1

Yapmamın bir yolu singleton kullanmak.

Programınızı başlattığınızda singleton'unuzu başlatır ve sabit verilerle (muhtemelen çalıştırma için sahip olduğunuz bir özellik dosyasından) doldurursunuz. Bunu, değerlere ihtiyacınız olan her sınıfta alıp kullanın.


Uyarı: Bazen tek parçacıklı çok iş parçacıklı kodda erişimi seri hale getirdim. Bu yüzden profil oluşturma aşamasının bir parçası olarak bunu kontrol etmek isteyebilirsiniz.
Richard

Onları kesinlikle tek bir cihaza koymam ... Pratikte bu sabitler gelecekte modelinizi farklı bir alana uyguladığınızda değişmeyecek. Tek bir tona sahip olmak, farklı parametrelerle test etmeyi çok zorlaştırır.
André

Hepsi sabit. Burada bir single'a gerek yok. Statik bir erişimci sınıfı burada daha iyi bir kullanımdır. Daha da iyisi, değerlerin bir yapılandırma dosyasından alındığı statik bir sınıf olabilir (böylece son kullanıcınız bir hata görürse veya daha fazla hassasiyet isterse, yeni bir derleme almadan yapılandırma dosyasını ayarlayabilir).
Tüplü Steve

Singletons nadiren, eğer varsa, iyi bir fikirdir. Bağımlılık enjeksiyonu çok daha temiz ve daha esnek bir çözümdür. Ancak, sadece sabitler ile, sabitleri bir yerde bir başlıkta tuttuklarını söyleyebilirim.
mascoj
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.