Güce Yükselt


12

Meydan okuma

Zorluk, pozitif sayılar a, sıfır olmayan bir sayı bve çıktı alan bir program yazmaktıra^b (güce yükseltilir). Yalnızca + - * / abs()matematiksel işlevler / işleçler olarak kullanabilirsiniz . Bunlar yalnızca skaler değerlere uygulanabilir, tüm listelere veya dizilere uygulanamaz.

Örnekler:

1.234 ^ 5.678 = 3.29980
4.5   ^ 4.5   = 869.874
4.5   ^-4.5   = 0.00114959

İlgili: http://xkcd.com/217/

ayrıntılar

Konsolda kullanmak için bir işlev veya benzer bir yapı yazabilirsiniz. Konsol girişini kullanamıyorsanız, her iki sayının da standart çıktı veya bir dosyaya yazma yoluyla değişkenlere ve çıkışa kaydedildiğini varsayabilirsiniz. Çıktı en az 4 anlamlı basamağa doğru olmalıdır. Her iki varsayabiliriz ave bsıfırdan farklı bulunmaktadır. 1 dakikadan fazla önemli bir çalışma süresi kabul edilemez. En az bayt sayısı kazanacaktır. Lütfen programınızı ve algoritmanızı açıklayınız.

EDIT: Yalnızca pozitif bazlar dikkate alınmalıdır. Varsayabilirsiniz a>0. Her iki sayının da tamsayı olması gerekmediğini unutmayın !!!


3
Ondalık bir güce yükseltmemizi mi istiyorsun? Demek gibi, 4.5 ^ 4.5?
fuandon

1
Bu, taban negatifse hayali sayılar çıkarmamız gerektiği anlamına mı geliyor?
bebe

1
Çıktı ne için -0.5 ** 0.5olmalı?
Dennis

Tamam, bu davayı düşünmedim, teşekkür ederim: Negatif bazlar doğru bir şekilde uygulanmamalıdır. @fuandon tam olarak, gerçek sayıların ondalıkları olabilir (en azından çoğu programlama dilinde =)
flawr

B <0: `` 4.5 ^ -4.5 = 0.0011496 '' ile bir test örneği eklemek istiyorum
edc65

Yanıtlar:


3

Python, 77

Diğer bazı cevaplarda olduğu gibi bu, log ve exp'ye dayanmaktadır. Ancak fonksiyonlar, adi diferansiyel denklemlerin sayısal olarak çözülmesi ile hesaplanır.

def f(a,b,y=1):
 if a<1:a=1/a;b=-b
 while a>1:a/=1e-7+1;y*=b*1e-7+1
 return y

İhtiyaçları karşılıyor mu? Sorudaki örnekler için, evet. Büyük a için çok uzun zaman alacaktır. Büyük a veya b için yanlış olur.

Örnekler:

a            b            f(a, b)      pow(a, b)      <1e-5 rel error?
       1.234        5.678       3.2998       3.2998   OK
         4.5          4.5      869.873      869.874   OK
         4.5         -4.5   0.00114959   0.00114959   OK
         0.5          0.5     0.707107     0.707107   OK
         0.5         -0.5      1.41421      1.41421   OK
          80            5  3.27679e+09   3.2768e+09   OK
     2.71828      3.14159      23.1407      23.1407   OK

Güncelleme: Flawr matematik hakkında daha fazla bilgi istedi, işte burada. Aşağıdaki başlangıç ​​değer problemlerini düşündüm:

  • x '(t) = x (t), x (0) = 1 ile. Çözelti exp (t)' dir.
  • y '(t) = (t) ile, y (0) = 1 ile. Çözelti exp (bt).

Eğer t değerini x (t) = a olacak şekilde bulabilirsem, y (t) = exp (bt) = a ^ b olurum. Bir başlangıç ​​değeri problemini sayısal olarak çözmenin en basit yolu Euler yöntemidir . Fonksiyonun sahip olması gereken türevi hesaplarsınız ve daha sonra türev yönünde ve onunla orantılı bir adım atarsınız, ancak küçük bir sabitle ölçeklendirilirsiniz. Yaptığım şey bu, x bir büyüklüğe kadar küçük adımlar atın ve o zaman y'nin ne olduğunu görün. Ben de öyle düşünmüştüm. Kodumda, t asla açıkça hesaplanmaz (1e-7 * while döngüsünün adım sayısıdır) ve bunun yerine x için hesaplamalar yaparak bazı karakterler kaydettim.


Harika görünüyor, başka bir yaklaşım görmek beni mutlu ediyor! Bize bu diferansiyel denklemlerden biraz daha bahsedebilir misiniz? Genellikle ne olduklarını biliyorum ama program onları nasıl kullandığını
anlayamadım

@flawr: Tamam, matematikle ilgili daha fazla ayrıntıyla güncelledim.
tekrar ısıtıldı

6

JavaScript (E6) 155175191

Düzenle 2 @bebe tarafından önerildiği gibi, özyinelemeli işlev (daha kötü ama daha kısa performans)
kullanmak 'Çok fazla özyineleme' önlemek için R işlevini biraz değiştirdi
Test paketi eklendi. İşlev, <3000 bazları ve -50..50 aralığındaki üsler için iyi performans gösterir.
Düzenleme golfed fazla ve daha iyi hassasiyet

Herhangi bir gerçek sayı rasyonel bir sayı ile yaklaşık olabilir (ve aslında IEEE standart 'gerçek' sayılar rasyonelleri saklar). Herhangi bir rasyonel sayı, a ve b tam sayıları olan a / b fraksiyonu olarak ifade edilebilir. x ^ (a / b) (x ^ a) 'nın kök b veya (x'in kök b) ^ a' nın b köküdür. Tamsayı imlenmesi kare ile oldukça kolaydır. Tam sayı kökü sayısal yöntemler kullanılarak tahmin edilebilir.

kod

P=(x,e)=>(
  f=1e7,e<0&&(x=1/x,e=-e),
  F=(b,e,r=1)=>e?F(b*b,e>>1,e&1?r*b:r):r,
  R=(b,e,g=1,y=1e-30,d=(b/F(g,e-1)-g)/e)=>d>y|d<-y?R(b,e,g+d,y/.99):g,
  F(R(x,f),e*f)
)

FireFox veya FireBug konsolunda test et

for (i=0;i<100;i++)
{
  b=Math.random()*3000
  e=Math.random()*100-50
  p1=Math.pow(b,e) // standard power function, to check
  p2=P(b,e)
  d=(p1-p2)/p1 // relative difference
  if (!isFinite(p2) || d > 0.001) 
    console.log(i, b, e, p1, p2, d.toFixed(3))
}

İyi iş, çok kesin değil ama algoritma güzel =)
flawr

Eğer bu nedir açıklayabilir e&1&&(r*=b)çarparak dışında yapar rtarafından b?
flawr

1
@flawrif(e&1 != 0) r *= b
bebe

Teşekkürler, bu istismarın farkında değildim, ama golf için hoş bir şey gibi görünüyor =)
flawr

1
işte çalışma kodu: P=(x,e)=>(F=(b,e,r=1)=>e?F(b*b,e>>1,e&1?r*b:r):r,R=(b,e,g=1,y=1e-16,d=(b/F(g,e-1)-g)/e)=>d>y|d<-y?R(b,e,g+d):g,e<0&&(x=1/x,e=-e),f=1<<24,F(R(x,f),e*f))(yorgun olmalıyım)
bebe

6

Haskell, 85 90

Standart exp-log algoritması. Şimdi farklı bir isimle, birkaç karakter daha tıraş:

a%b|a>1=1/(1/a)%b|0<1=sum$scanl((/).((-b*foldr1(\n b->(1-a)*(b+1/n))c)*))1c
c=[1..99]

raiseşimdi (%)veya %daha az bayt tüketmesini sağlamak için bile adlandırılır veya infix gösterimi olarak adlandırılır :4.5%(-4.5)

Çözümsüz sürüm sadece 172 bayt kullanır:

raise a b | a > 1     = 1 / raise (1/a) b
          | otherwise = expo (-b* ln (1-a))

ln x = foldr1 (\n a -> x*a+x/n) [1..99]

expo x = sum $ scanl ((/) . (x*)) 1 [1..99]

4

JS (ES6), 103 bayt

t=(x,m,f)=>{for(r=i=s=u=1;i<1<<7+f;r+=s/(u=i++*(f?1:u)))s*=m;return r};e=(a,b)=>t(b,t(a,1-1/a,9)*b-b,0)

Örnekler:

e(1.234,5.678) = 3.299798925315965
e(4.5,4.5)     = 869.8739233782269
e(4.5,-4.5)    = 0.0011495918812070608

Taylor serisini kullan.
b^x = 1 + ln(b)*x/1! + (ln(b)*x)^2/2! + (ln(b)*x)^3/3! + (ln(b)*x)^4/4! + ...
ile doğal logaritma yaklaşım :
ln(b) = (1-1/x) + (1-1/x)^2/2 + (1-1/x)^3/3 + (1-1/x)^4/4 + ...

Hesaplamak için 128 yineleme kullandım b^x(faktöriyelden dolayı daha fazla yineleme zor) ve 262144 yinelemeln(b)


Belki daha az golf e(80,5) ->1555962210.2240903oynamalısınız, ancak daha fazla hassasiyet eklemelisiniz: - 3276800000
edc65

@ edc65, haklısın, 5 karakter daha düzeltildi.
Michael M.

1
Bazı farklı yaklaşımları görmek çok güzel!
flawr

3

golflua 120

Gerçeğini kullanıyorum

a^b = exp(log(a^b)) = exp(b*log(a))

ve kendi yazdığı logve expişlevleri. Terminalde çalıştırıldığında değerler ave byeni satırlara girilmesi gerekir:

\L(x)g=0~@ i=1,50 c=(x-1)/x~@j=2,i c = c*(x-1)/x$g=g+c/i$~g$\E(x)g=1;R=1e7~@i=1,R g=g*(1+x/R)$~g$a=I.r()b=I.r()w(E(b*L(a)))

Örnek çalışmalar:

4.5, 4.5  ==> 869.87104890175
4.5, -4.5 ==> 0.0011495904124065
3.0, 2.33 ==> 12.932794624815
9.0, 0.0  ==> 1
2.0, 2.0  ==> 3.9999996172672

Golf edilmemiş bir Lua versiyonu,

-- returns log
function L(x)
   g = 0
   for i=1,50 do
      c=(x-1)/x
      for j=2,i do
         c = c*(x-1)/x
      end
      g = g + c/i
   end
   return g
end

-- returns exp
function E(x)
   g=1;L=9999999
   for i=1,L do
      g=g*(1+x/L)
   end
   return g
end

a=io.read()
b=io.read()

print(E(b*L(a)))
print(a^b)

Bazı örnek çıktılar sağlayabilir misiniz?
flawr

@flawr: Sanırım yapabilirim ... ve şimdi bitti
Kyle Kanos
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.