Hangi derece kendi kosinüs değerine eşittir problemi

Merhaba arkadaşlar, bugün ekşisözlük’te ilgimi çeken bir yazıyla karşılaştım ve bu yazı bana bir ilham verdi ve biraz Python egzersizi yapmak istedim.

Yazının bana ilham veren kısmını paylaşıyorum:

tam sonuç bulmanın imkansız olduğu problemlere örnek olarak cosx=x denklemi verilebilir

Bu bahsedilen problemin cevabını Python ile bulmaya çalıştım. Kodları ve açıklamalarını sizlerle paylaşıyorum:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from math import radians, cos
from numpy import arange

def x_is_cosx(start: float = 0.99, end: int = 1, step: int = 2) -> float:
    global __start__
    try:
        for i in arange(start, end, 10 ** -step):
            if round(cos(radians(i)), step) == round(i, step):
                __start__ = f"{start}{str(cos(radians(i)))[step + 2]}"
                print(__start__, step + 1)
                return x_is_cosx(float(__start__), end, step + 1)
    except MemoryError:
        if round(cos(radians(float(__start__))), step - 1) == \
                round(float(__start__), step - 1):
            return cos(radians(float(__start__)))

x = x_is_cosx()
assert x == cos(radians(x))
print(x)

Yukarıdaki kodları çalıştırdığımızda, virgülden sonra 16 basamaklı 0.9998477415310881 sayısının ekrana yazdırıldığını göreceğiz. Python’a göre bu sayının kosinüs değeri tıpkı sinüs 0’ın 0’a eşit olması gibi kendisine eşittir.

Bu değer nasıl hesaplanıyor izninizle şimdi ondan bahsetmek istiyorum:

  1. x_is_cosx()'in ön-tanımlı olarak 3 tane parametresi var. Bunlardan birisi değeri 0.99 olan start parametresi, bir diğeri, değeri 1 olan end parametresi ve son olarak değeri 2 olan step parametresidir.

  2. __start__ isminde, global olarak tanımlanan bir değişken görüyorsunuz. Bu değişkenin değeri try blokunda veriliyor ve değişken except blokunda kullanılabilsin diye değişken global ifadesi ile kullanılıyor.

  3. numpy’nin arange isimli bir fonksiyonu vardır. tıpkı range fonksiyonuna benzer. ancak bu fonksiyon ile çok daha küçük aralıklar arasında sayilar iceren bir dizi tanımlayabiliriz. İşte bu arange dizisinin ilk parametresine start, ikinci parametresine end ve üçüncü parametresi ne ise 10 ** -step parametreleri atanıyor. for döngüsü ile bu dizinin elemanları tek tek ziyaret edilir.

  4. Ziyaret edilen sayının kosinüs değeri hesaplanır ve bu sayının step basamağına kadar olan kısmı ile sayının kosinüs değerinin step basamağına kadar olan kısmı birbirine eşitse __start__ isimli yeni başlangıç sayısı oluşturulur. Bu başlangıç sayısının özelliği şu: start sayısının hemen yanına, start’ın kosinüsünün step + 1. basamağında yer alan sayı eklenir. Yani start 2 basamaklı bir sayıysa, __start__ ilk etapta 3 basamaklı bir sayı olur.

  5. Daha sonra x_is_cosx() fonksiyonu yeni __start__ ve step değerleri ile tekrar çağrılır. step sayısının yeni değeri 1 fazlasıdır. Yukarıda anlattığım işlemlerin hepsi tekrar edilir. Bu kez oluşacak yeni __start__ sayısı 4 basamaklı ve step sayısı ise 4 olacaktır. Fonksiyonun tekrar çağrılması bildiğiniz gibi for döngüsü altında gerçekleştiği için return burada break gibi bir işlev görür.

  6. Fonksiyon, 13. basamakta bir MemoryError hatası yükseltir. Ve bu kez step sayısının değeri 1 birim azaltılır ve __start__ sayısı değiştirilmez. Bu __start__ sayısının kosinüs değerinin step - 1. basamağına kadar olan kısmı, __start__ sayısının, step - 1. basamağına kadar olan kısmıyla aynıysa, __start__ sayısının kosinüs değeri geri döner.

  7. x_is_cosx fonksiyonunundan geri dönen değer x isimli bir değişkene kaydedilir.

  8. Bu x sayısının kendi kosinüs değerine eşit olduğu iddia edilir. Eğer iddia doğruysa, x sayısı ekrana yazdırılır.

Şimdi sizlere bir soru sormak istiyorum: kosinüsü kendisine eşit olan tek sayı 0.9998477415310881 sayısı mıdır? Gördüğüm kadarıyla Python bir sayının kosinüs değerini hesaplarken virgülden sonra en fazla 16 basamak gidebiliyor. Eğer kosinüs fonksiyonu daha fazla basamak hesaplayabilseydi, bu sayı değişirdi diye tahmin ediyorum, yanılıyor muyum acaba?

1 Beğeni

File “/home/evo/Masaüstü/df.py”, line 22, in
assert x == cos(radians(x))
TypeError: must be real number, not NoneType
------------------------------------------+
Böyle bir hata alıyorum. Neden olabilir sizce?
------------------------------------------+
Python: 3.7.4 (default, Jul 16 2019) [GCC 9.1.0]
Numpy: 1.17.0

Sizde şu koşul sağlanmamış muhtemelen.

        if round(cos(radians(float(__start__))), step - 1) == \
                round(float(__start__), step - 1):
            return cos(radians(float(__start__)))

Bu arada try blokundaki return ifadesinden önce print(__start__, step + 1) ifadesini kodlarınıza eklemenizi rica ediyorum. Sizin bilgisayarinizda MemoryError hangi basamakta yukseltiliyor bakalım.

1 Beğeni

Selamlar. Öncelikle, kodunuzda dikkatinizi çekmek istediğim bir hata var. Bu fonksiyon, cos(x) = x eşitliği yerine cos(rad(x)) = x eşitliği için çözüm arıyor. (İlginç bir şey olmuş bu arada :​​P)

In [3]: rad(0.9998477415310881)
Out[3]: 0.017450635108346737

In [4]: cos(rad(0.9998477415310881))
Out[4]: 0.9998477415310881

In [5]: 0.017450635108346737 != 0.9998477415310881
Out[5]: True

Aslında aradığınız değer Dottie Number olarak geçiyor. Diğer sorularınızın cevabını ise trigonometrik fonksiyonların nasıl hesaplandığına dair araştırma yaparsanız bulabilirsiniz diye düşünüyorum. (Google’da arayabileceğiniz konular: Taylor Series, Remez Algorithm, CORDIC)

Selam.

Mesela cos(60) değeri 1/2 yapar değil mi? Python ile cos(60)'ı hesaplamaya çalışırken şöyle yapmıyor muyuz?

>>> from math import cos, radians
>>> cos(radians(60))
0.5000000000000001

Eğer cos(60) yazılırsa, şöyle bir sonuç oluşuyor:

>>> cos(60)
-0.9524129804151563

cos(x) değil de cos(radians(x)) kullanmamın sebebi bu.

Tavsiyeleriniz için teşekkür ederim. Bir ara bunlara daha detaylı bakmam lazım. Bu arada paylaştığım kodlardan nasıl bir sonuç elde ettiniz paylaşabilir misiniz?

1 Beğeni

Yardımınız için teşekkürler ancak Linux kaynaklı bir problem galiba.
Windows bilgisayarda sorun yaşamadım. Sorunuza gelecek olursak benim çözümüm aşağıdaki gibidir;

"""
cos(x) = x eşitliğini sağlayan bir kök bulunmamaktadır. 
Ancak nümerik metod ile Çözüm kümesini
y = cos x  ve  y = x fonksiyonlarının 
kesim noktası olarak düşünebilirsiniz.
Bunun için Newton-Rapshon yöntemi kullanacağız.
f(x) = x- cos(x)
f'(x) = 1 + sin(x) //türevi
"""


import math

def x_cosx(x): 
    return x - math.cos(x) 
  
def turev_x_cosx(x): 
    return 1 + math.sin(x) 
  
# Kök bulma yarılama newton
def x_cosxx(x): 
    h = x_cosx(x) / turev_x_cosx(x) 
    while abs(h) >= 0.00001: 
        h = x_cosx(x) / turev_x_cosx(x)
        x = x - h 
      
    print("fonksiyonun kökü : x =","%.16f"% x) 

x0 = 0.5 # yarılama yöntemminde kökün 0 ile 1 arasında değer 
#aldığını biliyoruz. Buna göre ilk tahmini kökümüz 0,5
print(x_cosxx(x0))

Cevap: x= ~0.7390851332151607 olarak düşünebiliriz.yazbel

@evoloji

Siz de, açıyı radyan birimiyle hesaplamışsınız.

Örneğin sizin yazdığınız gibi cos fonksiyonunu kullanırsak şöyle bir durumla karşılaşıyoruz:

>>> from math import cos
>>> cos(60)
-0.9524129804151563
>>> cos(radians(60))
0.5000000000000001

Halbuki cos(60), 0.5 değerine eşittir. 0.5 değerini veren cos(60) ifadesindeki 60’ın birimi derecedir, radyan değildir. Ama sizin kullandığınız şekilde kullanırsak bu değer radyan olur. Yani cos(60) değerini bulmak için, cos(radians(60)) kullanmak gerekiyor. İsterseniz aşağıdaki siteden deneyin. 0.9998477415310881 sayısının derece cinsinden kosinüsünü almaya çalışın.

>>> cos(60 / (180 / pi)) == cos(radians(60)) == 0.5000000000000001
True

math. cos ( x )

Return the cosine of x radians.

Benim yapmaya çalıştığım şey şu: nasıl ki 0 derecenin sinüs’ü 0’a eşittir, kaç derecenin kosinüsü sayısal olarak kendisine eşittir sorusunun cevabını bulmaya çalışmak. Ki, bir cevap buldum ancak cevapla birlikte bir soru sordum, o sorunun cevabını aslında merak ediyorum.

@dildeolupbiten
Merhaba,

Cos(60°) = cos(pi/3)
Yani pi radyan = 180°
Biz derece işareti koymadığımız zaman söz konusu sayı radyandır zaten. Python da öyle algılıyor.
https://docs.python.org/2/library/math.html

`math.` `cos` ( *x* )

Return the cosine of *x* radians.
>>> print(math.cos((math.pi/3)))
0.5000000000000001
>>> print(math.pi/3)
1.0471975511965976
>>> print(math.degrees(1.0471975511965976))
59.99999999999999

Demek istediğimi anladınız sanıyorum.
Yani 60 derecenin kosinüs değerini hesaplamak için python konsoluna şu ifadeleri yazmamız gerekir:

>>> cos(radians(60))
0.5000000000000001

Ben de hangi derecenin kosinüs değeri sayısal olarak kendisine eşittir, bunu bulmaya çalıştım.

>>> cos(radians(0.9998477415310881))
0.9998477415310881
1 Beğeni

Evet sizi şimdi anladım.
Ancak başlık " Hangi sayı kendi kosinüs değerine eşittir problemi" bu şekliyle eksik ifadeli duruyor gibi “Hangi derece, kosinüs değerine eşittir” şeklinde daha açıklayıcı olabilir belki. :slight_smile:

Şimdi sil baştan düşüneceğiz. :smiley:

Haklısınız, başlıkta bir değişiklik yapmam gerekecek. Bu arada bu cevapla alakalı bir soru sormuştum. O soruya aslında cevap arıyorum. Yani derece değeri bulundu ama aklıma da bir soru takıldı.

Mesela rapidtables sitesinde 8 basamak gösteriliyor sadece.

Fonksiyon her öz-yinelemesinde yeni bir start değeri alıyor. bu değer __start__ değişkeni oluyor. Mesela kodları çalıştırdığımız zaman şöyle bir çıktı almaya başlıyoruz:

0.999 3
0.9998 4
0.99984 5
0.999847 6
0.9998477 7
0.99984774 8
0.999847741 9
0.9998477415 10
0.99984774153 11
0.999847741531 12
0.9998477415310 13
0.9998477415310881

Bu çıktılardaki sayıların yanında basamak sayılarının da yer aldığını görüyoruz. Python en son 13. basamağı hesaplıyor ve sonra da zaten bir MemoryError hatası yükseltilyor. Ve bu aşamada da except blokunda kodlar çalışıyor.

Aslında bu sayının sonsuz olduğunu ve bunun da Pi sayısının sonsuz oluşundan kaynaklanacağını düşünüyorum. Yani derecesinde kendi kosinüs değerine yakın bir sayı sonsuzdur.

x° = x * (pi/180°) -> görüldüğü gibi buradan sonlu elde etmek mümkün değildir.

1 Beğeni

Aynen ben de böyle düşünüyorum. Python’ın bize verdiği değer, bir yerde Python’ın ve bilgisayarın kapasitesine göre bulabildiği değer. Yani aslında bu sorunun tam bir cevabı yok sadece elimizdeki araçların özelliklerine göre cevaplar alabiliriz.

1 Beğeni

beyin jimnastiği için çok iyi bir problem. bunu pythonla çözecek kadar tecrübeli sayılmam ama java ile çözmek için uğraşacağım.