Özeti düzenleyin
- İlk cevabım sadece kodun çok sayıda tekrarlanmış hesaplama içerdiğini ve güçlerin çoğunun 1 / 3'lük faktörleri içerdiğini belirtti. Örneğin,
pow(x, 0.1e1/0.3e1)
ile aynıdır cbrt(x)
.
- İkinci düzenlemem tamamen yanlıştı ve üçüncü düzenlemem bu yanlışlık üzerine yorum yaptı. İnsanları 'M' harfiyle başlayan sembolik matematik programlarının kahin benzeri sonuçları değiştirmekten korkmasına neden olan şey budur. Bu düzenlemeleri kaldırdım (yani,
grev yaptım ) ve bunları bu cevabın mevcut revizyonunun altına ittim. Ancak onları silmedim. Ben insanım. Hata yapmak bizim için çok kolay.
- Dördüncü düzenleme doğru, söz konusu dolambaçlı ifadesini temsil ettiği çok kompakt ifadesini geliştirdi EĞER parametreleri
l1
, l2
ve l3
pozitif reel sayılardır ve eğer a
sıfır olmayan gerçek sayıdır. (Bu katsayıların özel doğası hakkında OP'den henüz haber alamadık. Sorunun doğası göz önüne alındığında, bunlar makul varsayımlardır.)
- Bu düzenleme, bu ifadelerin nasıl basitleştirileceğine ilişkin genel soruna cevap vermeye çalışır.
Her şey sırayla
Hatalardan kaçınmak için C ++ kodunu oluşturmak için Maple kullanıyorum.
Maple ve Mathematica bazen bariz olanı gözden kaçırır. Daha da önemlisi, Maple ve Mathematica kullanıcıları bazen hata yapar. "Çoğu zaman" veya hatta "neredeyse her zaman" yerine bazen "bazen" işarete daha yakındır.
Maple'ın söz konusu parametreleri anlatarak bu ifadeyi basitleştirmesine yardımcı olabilirdiniz. Eldeki örnekte, şüpheli l1
, l2
ve l3
olan pozitif reel sayılar ve a
sıfır olmayan gerçek sayıdır. Eğer durum buysa, bunu söyle. Bu sembolik matematik programları tipik olarak eldeki miktarların karmaşık olduğunu varsayar. Etki alanını kısıtlamak, programın karmaşık sayılarda geçerli olmayan varsayımlar yapmasına izin verir.
Sembolik matematik programlarındaki bu büyük karışıklıklar nasıl basitleştirilir (bu düzenleme)
Sembolik matematik programları tipik olarak çeşitli parametreler hakkında bilgi sağlama yeteneği sağlar. Bu yeteneği kullanın, özellikle de sorununuz bölme veya üs alma içeriyorsa. Eldeki örnekte, Maple bu kadar anlatarak bu ifadeyi basitleştirmek yardımcı olabilirdi l1
, l2
ve l3
olan pozitif reel sayılar ve a
sıfır olmayan gerçek sayıdır. Eğer durum buysa, bunu söyle. Bu sembolik matematik programları tipik olarak eldeki miktarların karmaşık olduğunu varsayar. Etki alanını kısıtlamak, programın x b x = (ab) x gibi varsayımlar yapmasına izin verir . Bu yalnızca olduğunu a
ve b
pozitif reel sayılardır ve eğer x
gerçek. Karmaşık sayılarda geçerli değildir.
Sonuçta, bu sembolik matematik programları algoritmaları takip eder. Yardım edin. Kodu oluşturmadan önce genişletmeyi, toplamayı ve basitleştirmeyi deneyin. Bu durumda, onlardan bir faktör içeren terimler toplanmış olabilir mu
ve bir faktör içerenler K
. Bir ifadeyi "en basit biçimine" indirgemek biraz sanattır.
Üretilen kodun çirkin bir karmaşasını gördüğünüzde, bunu dokunmamanız gereken bir gerçek olarak kabul etmeyin. Kendiniz basitleştirmeye çalışın. Sembolik matematik programının kodu oluşturmadan önce neye sahip olduğuna bakın. İfadenizi nasıl çok daha basit ve daha hızlı bir şeye indirdiğime ve Walter'ın cevabının benim birkaç adım daha ileriye gittiğine bakın . Büyülü tarif yok. Büyülü bir tarif olsaydı, Maple onu uygular ve Walter'ın verdiği cevabı verirdi.
Spesifik soru hakkında
Bu hesaplamada çok fazla toplama ve çıkarma yapıyorsunuz. Neredeyse birbirini iptal eden şartlarınız varsa başınız büyük belaya girebilir. Diğerlerine hakim olan bir teriminiz varsa, çok fazla CPU harcıyorsunuz.
Ardından, tekrarlanan hesaplamalar yaparak çok fazla CPU harcarsınız. -ffast-math
Derleyicinin IEEE kayan noktasının bazı kurallarını ihlal etmesine izin veren etkinleştirmediyseniz , derleyici bu ifadeyi sizin için basitleştirmeyecektir (aslında, yapmamalıdır). Bunun yerine tam olarak ne yapmasını söylediğinizi yapacak. En azından, l1 * l2 * l3
bu karışıklığı hesaplamadan önce hesaplamalısınız.
Son olarak, pow
çok yavaş arama yapıyorsunuz . Bu aramaların birçoğunun (l1 * l2 * l3) (1/3) biçiminde olduğuna dikkat edin . Bu çağrıların çoğu pow
tek bir çağrı ile gerçekleştirilebilir std::cbrt
:
l123 = l1 * l2 * l3;
l123_pow_1_3 = std::cbrt(l123);
l123_pow_4_3 = l123 * l123_pow_1_3;
Bununla,
X * pow(l1 * l2 * l3, 0.1e1 / 0.3e1)
olur X * l123_pow_1_3
.
X * pow(l1 * l2 * l3, -0.1e1 / 0.3e1)
olur X / l123_pow_1_3
.
X * pow(l1 * l2 * l3, 0.4e1 / 0.3e1)
olur X * l123_pow_4_3
.
X * pow(l1 * l2 * l3, -0.4e1 / 0.3e1)
olur X / l123_pow_4_3
.
Maple bariz olanı kaçırdı.
Örneğin, yazmanın çok daha kolay bir yolu var
(pow(l1 * l2 * l3, -0.1e1 / 0.3e1) - l1 * l2 * l3 * pow(l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1)
Varsayarak l1
, l2
ve l3
gerçek oldukça karmaşık sayılar daha, ve gerçek küp kök (yerine prensibi kompleks kök dışında) ekstre edilmesi için olan, yukarıda azaltır
2.0/(3.0 * pow(l1 * l2 * l3, 1.0/3.0))
veya
2.0/(3.0 * l123_pow_1_3)
Kullanılması cbrt_l123
yerine l123_pow_1_3
, söz konusu pis ifade etmek azaltır
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
mu/(3.0*l123)*( pow(l1/cbrt_l123,a)*(2.0*N1-N2-N3)
+ pow(l2/cbrt_l123,a)*(2.0*N2-N3-N1)
+ pow(l3/cbrt_l123,a)*(2.0*N3-N1-N2))
+K*(l123-1.0)*(N1+N2+N3);
Her zaman iki kez kontrol edin, ancak her zaman basitleştirin.
Yukarıdakilere ulaşmak için attığım adımlardan bazıları:
T=(mu*(pow(l1*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a*(pow(l1*l2*l3,-0.1e1/0.3e1)-l1*l2*l3*pow(l1*l2*l3,-0.4e1/0.3e1)/0.3e1)*pow(l1*l2*l3,0.1e1/0.3e1)/l1-pow(l2*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l1/0.3e1-pow(l3*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l1/0.3e1)/a+K*(l1*l2*l3-0.1e1)*l2*l3)*N1/l2/l3+(mu*(-pow(l1*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l2/0.3e1+pow(l2*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a*(pow(l1*l2*l3,-0.1e1/0.3e1)-l1*l2*l3*pow(l1*l2*l3,-0.4e1/0.3e1)/0.3e1)*pow(l1*l2*l3,0.1e1/0.3e1)/l2-pow(l3*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l2/0.3e1)/a+K*(l1*l2*l3-0.1e1)*l1*l3)*N2/l1/l3+(mu*(-pow(l1*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l3/0.3e1-pow(l2*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a/l3/0.3e1+pow(l3*pow(l1*l2*l3,-0.1e1/0.3e1),a)*a*(pow(l1*l2*l3,-0.1e1/0.3e1)-l1*l2*l3*pow(l1*l2*l3,-0.4e1/0.3e1)/0.3e1)*pow(l1*l2*l3,0.1e1/0.3e1)/l3)/a+K*(l1*l2*l3-0.1e1)*l1*l2)*N3/l1/l2;
l123 = l1 * l2 * l3;
T=(mu*(pow(l1*pow(l123,-1.0/3),a)*a*(pow(l123,-1.0/3)-l123*pow(l123,-4.0/3)/3)*pow(l123,1.0/3)/l1-pow(l2*pow(l123,-1.0/3),a)*a/l1/3-pow(l3*pow(l123,-1.0/3),a)*a/l1/3)/a+K*(l123-1.0)*l2*l3)*N1/l2/l3+(mu*(-pow(l1*pow(l123,-1.0/3),a)*a/l2/3+pow(l2*pow(l123,-1.0/3),a)*a*(pow(l123,-1.0/3)-l123*pow(l123,-4.0/3)/3)*pow(l123,1.0/3)/l2-pow(l3*pow(l123,-1.0/3),a)*a/l2/3)/a+K*(l123-1.0)*l1*l3)*N2/l1/l3+(mu*(-pow(l1*pow(l123,-1.0/3),a)*a/l3/3-pow(l2*pow(l123,-1.0/3),a)*a/l3/3+pow(l3*pow(l123,-1.0/3),a)*a*(pow(l123,-1.0/3)-l123*pow(l123,-4.0/3)/3)*pow(l123,1.0/3)/l3)/a+K*(l123-1.0)*l1*l2)*N3/l1/l2;
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T=(mu*(pow(l1/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l1-pow(l2/cbrt_l123,a)*a/l1/3-pow(l3/cbrt_l123,a)*a/l1/3)/a+K*(l123-1.0)*l2*l3)*N1/l2/l3+(mu*(-pow(l1/cbrt_l123,a)*a/l2/3+pow(l2/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l2-pow(l3/cbrt_l123,a)*a/l2/3)/a+K*(l123-1.0)*l1*l3)*N2/l1/l3+(mu*(-pow(l1/cbrt_l123,a)*a/l3/3-pow(l2/cbrt_l123,a)*a/l3/3+pow(l3/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l3)/a+K*(l123-1.0)*l1*l2)*N3/l1/l2;
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
(mu*( pow(l1/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l1
-pow(l2/cbrt_l123,a)*a/l1/3
-pow(l3/cbrt_l123,a)*a/l1/3)/a
+K*(l123-1.0)*l2*l3)*N1/l2/l3
+(mu*(-pow(l1/cbrt_l123,a)*a/l2/3
+pow(l2/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l2
-pow(l3/cbrt_l123,a)*a/l2/3)/a
+K*(l123-1.0)*l1*l3)*N2/l1/l3
+(mu*(-pow(l1/cbrt_l123,a)*a/l3/3
-pow(l2/cbrt_l123,a)*a/l3/3
+pow(l3/cbrt_l123,a)*a*2.0/(3.0*cbrt_l123)*cbrt_l123/l3)/a
+K*(l123-1.0)*l1*l2)*N3/l1/l2;
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
(mu*( pow(l1/cbrt_l123,a)*2.0/(3.0*cbrt_l123)*cbrt_l123/l1
-pow(l2/cbrt_l123,a)/l1/3
-pow(l3/cbrt_l123,a)/l1/3))*N1/l2/l3
+K*(l123-1.0)*l2*l3*N1/l2/l3
+(mu*(-pow(l1/cbrt_l123,a)/l2/3
+pow(l2/cbrt_l123,a)*2.0/(3.0*cbrt_l123)*cbrt_l123/l2
-pow(l3/cbrt_l123,a)/l2/3))*N2/l1/l3
+K*(l123-1.0)*l1*l3*N2/l1/l3
+(mu*(-pow(l1/cbrt_l123,a)/l3/3
-pow(l2/cbrt_l123,a)/l3/3
+pow(l3/cbrt_l123,a)*2.0/(3.0*cbrt_l123)*cbrt_l123/l3))*N3/l1/l2
+K*(l123-1.0)*l1*l2*N3/l1/l2;
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
(mu*( pow(l1/cbrt_l123,a)*2.0/3.0/l1
-pow(l2/cbrt_l123,a)/l1/3
-pow(l3/cbrt_l123,a)/l1/3))*N1/l2/l3
+(mu*(-pow(l1/cbrt_l123,a)/l2/3
+pow(l2/cbrt_l123,a)*2.0/3.0/l2
-pow(l3/cbrt_l123,a)/l2/3))*N2/l1/l3
+(mu*(-pow(l1/cbrt_l123,a)/l3/3
-pow(l2/cbrt_l123,a)/l3/3
+pow(l3/cbrt_l123,a)*2.0/3.0/l3))*N3/l1/l2
+K*(l123-1.0)*N1
+K*(l123-1.0)*N2
+K*(l123-1.0)*N3;
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
mu*( ( pow(l1/cbrt_l123,a)*2.0/3.0/l1
-pow(l2/cbrt_l123,a)/l1/3
-pow(l3/cbrt_l123,a)/l1/3)*N1/l2/l3
+ (-pow(l1/cbrt_l123,a)/l2/3
+pow(l2/cbrt_l123,a)*2.0/3.0/l2
-pow(l3/cbrt_l123,a)/l2/3)*N2/l1/l3
+ (-pow(l1/cbrt_l123,a)/l3/3
-pow(l2/cbrt_l123,a)/l3/3
+pow(l3/cbrt_l123,a)*2.0/3.0/l3)*N3/l1/l2)
+K*(l123-1.0)*(N1+N2+N3);
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
mu*( pow(l1/cbrt_l123,a)*2.0/3.0/l1*N1/l2/l3
-pow(l2/cbrt_l123,a)/l1/3*N1/l2/l3
-pow(l3/cbrt_l123,a)/l1/3*N1/l2/l3
-pow(l1/cbrt_l123,a)/l2/3*N2/l1/l3
+pow(l2/cbrt_l123,a)*2.0/3.0/l2*N2/l1/l3
-pow(l3/cbrt_l123,a)/l2/3*N2/l1/l3
-pow(l1/cbrt_l123,a)/l3/3*N3/l1/l2
-pow(l2/cbrt_l123,a)/l3/3*N3/l1/l2
+pow(l3/cbrt_l123,a)*2.0/3.0/l3*N3/l1/l2)
+K*(l123-1.0)*(N1+N2+N3);
l123 = l1 * l2 * l3;
cbrt_l123 = cbrt(l123);
T =
mu/(3.0*l123)*( pow(l1/cbrt_l123,a)*(2.0*N1-N2-N3)
+ pow(l2/cbrt_l123,a)*(2.0*N2-N3-N1)
+ pow(l3/cbrt_l123,a)*(2.0*N3-N1-N2))
+K*(l123-1.0)*(N1+N2+N3);
Yanlış cevap, kasıtlı olarak alçakgönüllülük için tutuldu
Bunun etkilendiğini unutmayın. Yanlış.
Güncelleme
Maple bariz olanı kaçırdı. Örneğin, yazmanın çok daha kolay bir yolu var
(pow (l1 * l2 * l3, -0.1e1 / 0.3e1) - l1 * l2 * l3 * pow (l1 * l2 * l3, -0.4e1 / 0.3e1) / 0.3e1)
Varsayarak l1
, l2
ve l3
karmaşık sayılar yerine gerçek yerine, ve gerçek küp kök (yerine prensibi kompleks kök) vardır ekstre edilmesi, yukarıda sıfıra düşer. Bu sıfır hesaplaması defalarca tekrarlanır.
İkinci güncelleme
Matematiği doğru yaptıysam (matematiği doğru yaptığımın garantisi yoktur ), sorudaki çirkin ifade şu şekilde azalır:
l123 = l1 * l2 * l3;
cbrt_l123_inv = 1.0 / cbrt(l123);
nasty_expression =
K * (l123 - 1.0) * (N1 + N2 + N3)
- ( pow(l1 * cbrt_l123_inv, a) * (N2 + N3)
+ pow(l2 * cbrt_l123_inv, a) * (N1 + N3)
+ pow(l3 * cbrt_l123_inv, a) * (N1 + N2)) * mu / (3.0*l123);
Yukarıdaki varsayar l1
, l2
ve l3
pozitif reel sayılardır.
pow(l1 * l2 * l3, -0.1e1 / 0.3e1)
bir değişkenle değiştirmektir ... Yine de, hızlı mı yoksa yavaş mı çalıştığından emin olmak için kodunuzu kıyaslamanız gerekir.