Derece bağımsız değişkeni olan bir trig işlevi ne zaman -0.0 döndürmelidir?


10

Açı fonksiyonları oluştururken my_sind(d), my_cosd(d), my_tand(d)bu bir derece argüman yerine radyan kullanmadım ve 90 katları ile kesin cevaplar sağlanan, ben Sonuç bazen olduğunu fark -0.0ziyade 0.0.

my_sind( 0.0) -->  0.0
my_sind(-0.0) --> -0.0

my_sind(180.0) --> -0.0
my_sind(360.0) -->  0.0

sin()ve tan()tipik olarak belirli bir işaret sıfır girişi için aynı işaret sıfır sonucunu döndürür. Bu girdilerle my_sin()uyuşması mantıklı sin().

my_sind( 0.0) alike sin( 0.0) -->  0.0
my_sind(-0.0) alike sin(-0.0) --> -0.0

Soru : tam sayı ne için non_zero_n/ sonuç hiç döndürebilir gerektiğini -0.0için my_sind(180*non_zero_n), my_cosd(180*n + 180), my_tand(180*non_zero_n)?

Kodlamak yeterince kolaydır, bu yüzden sadece f(-0.0)üretir -0.0ve onunla yapılabilir. Başka herhangi bir f(x)geri dönüş yapmak -0.0için herhangi bir neden olup olmadığını ( sıfır olmayan ) xve bu işareti sigortalamanın önemini merak etmek basittir .


Not: Bu, 0.0vs.'nin neden -0.0oluştuğu sorusu değildir . Bu yüzden cos(machine_pi/4)geri dönmüyor 0.0. Bu 0.0ya da neslinin nasıl kontrol edileceği sorusu da değildir -0.0. Bunu en iyi tasarım sorusu olarak görüyorum.

Yanıtlar:


4

"En az sürpriz" tasarım ilkesi, rehberlik için önceden belirlenmiş işlevselliğe baktığımızı göstermektedir. Bu durumda, en yakın yerleşik işlevsellik IEEE Std 754-2008 (Kayan Nokta Aritmetiği için IEEE Standardı), bölüm 9 tarafından sağlanır sinpive cospisunulan işlevlerdir, bu işlevler geçerli ISO C ve ISO C ++ standartlarının bir parçası değildir, ancak CUDA gibi çeşitli programlama platformlarının matematik kütüphanelerine dahil edilmiştir.

Bu işlevler, π ile çarpmanın dolaylı olarak işlevin içinde gerçekleştiği sin (πx) ve cos (πx) değerlerini hesaplar. tanpitanımlanmamıştır, ancak matematiksel denkliğe dayanarak, fonksiyonelliğe göre fonksiyonellik sağladığı varsayılabilir tanpi(x) = sinpi(x) / cospi(x).

Şimdi tanımlayabilirsiniz sind(x) = sinpi(x/180), cosd(x) = cospi(x/180), tand(x) = tanpi(x/180)sezgisel bir şekilde. IEEE-754'ün 9.1.2 Bölümü sinpive için özel argümanların ele alınmasını açıklamaktadır cospi. Özellikle:

pozitif pozitif tamsayılar için sinPi (+ n) +0 ve sinPi (−n) −0'dir. Bu, uygun yuvarlama modları altında sinPi (−x) ve −sinPi (x) 'in tüm x için aynı sayı (veya her ikisi de NaN) olduğunu gösterir. n + ½ temsili olduğunda cosPi (n + ½) n tamsayısı için +0'dır.

IEEE 754-2008 standardı, belirtilen gereksinimler için bir gerekçe oluşturmaz, ancak ilgili bölümün erken taslağı şunları belirtir:

Fonksiyonun değeri sıfırsa, bu 0'ın işareti en iyi matematiksel fonksiyonun işaret fonksiyonunun sürekli uzantısı dikkate alınarak belirlenir.

Arasında inceleme 754 Çalışma Grubu Posta Arşivi ben üzerinden kazmak zamanım olmadı, ek fikir verebilir. Uygulayarak sind(), cosd()ve tand()yukarıda açıklandığı gibi, bu örnek vakalar tablosuna ulaşıyoruz:

SIND
 angle value 
  -540 -0
  -360 -0
  -180 -0
     0  0
   180  0
   360  0
   540  0

COSD
 angle value
  -630  0
  -450  0
  -270  0
   -90  0
    90  0
   270  0
   450  0

TAND
 angle value
  -540  0
  -360 -0
  -180  0
     0  0
   180 -0
   360  0
   540 -0

5

sin () ve tan () genellikle belirli bir işaret sıfır girişi için aynı işaret sıfır sonucunu döndürür

Genellikle doğru olabilir, çünkü:

  • Hız / doğruluk . Yeterince küçük çiftlerde için en iyi cevap sin(x)olduğunu x. Yani, yaklaşık olarak küçük sayılar için 1.49e-8x'in sinüsüne en yakın çift aslında x'in kendisidir ( sin için glibc kaynak koduna bakın )

  • Özel durumların ele alınması .

    Birkaç olağanüstü aritmetik işlem sıfırın işaretinden etkilenir; örneğin "1/(+0) = +inf"ama "1/(-0) = -inf". Yararlılığını korumak için işaret biti, süreklilik değerlendirmelerinden türetilen kurallara göre belirli aritmetik işlemlerle yayılmalıdır.

    IEEE standartlarında belirtilmese de sin (z) ve tan (z) gibi temel transandantal fonksiyonların ve tersleri ve hiperbolik analoglarının uygulamalarının benzer kurallara uyması beklenir. Uygulamasının değerinin yanı sıra değerinin sin(z) yeniden oluşturulması bekleniyorzz = ±O .

    ( Şube Karmaşık Temel Fonksiyonlar için Keser veya W. Kahan'dan Hiçbir Şey İşaret Biti Hakkında Hiçbir Şey )

    Negatif olarak imzalanmış sıfır, 0'a tek taraflı bir sınır olarak alttan yaklaşmanın matematiksel analiz kavramını yansıtır (düşünün 1 / sin(x): sıfır işareti büyük bir fark yaratır).

DÜZENLE

İkinci noktayı göz önüne alarak şöyle yazardım my_sind:

my_sind(-0.0) is -0.0
my_sind(0.0) is 0.0

Son C standart (F.10.1.6 sinve F.10.1.7 tanargüman ise, imzalı sıfır ile uygulamalar), belirtir yani ±0, o değiştirilmemiş döndürülür .

DÜZENLEME 2

Diğer değerler için bence bu bir yaklaşım meselesidir. Verilen M_PI<π:

0 = sin(π) < sin(M_PI)  1.2246467991473532e-16  +0.0
0 = sin(-π) > sin(-M_PI)  -1.2246467991473532e-16  -0.0
0 = sin(2*π) > sin(2*M_PI)  -2.4492935982947064e-16
0 = sin(-2*π) < sin(-2*M_PI)  2.4492935982947064e-16

Bu yüzden my_sind180 ° 'nin katlarında kesin cevaplar verirse geri dönebilir +0.0veya -0.0(birini diğerine tercih etmek için açık bir neden göremiyorum).

Eğer my_sindkullanımları bazı yaklaşım (örneğin bir degree * M_PI / 180.0dönüşüm formülü), bu kritik değerleri yaklaşıyor nasıl düşünmelisiniz.


Ne düşünüyorsun sind(180), sind(-180), sind(360), sind(-360),...?
chux - Monica

Güncelleme için teşekkürler. Belki de yazım net değil. Asıl soru my_trig(x)hiç olmadığı -0.0zaman dönmeli midir? |x|0.0
chux - Monica

"Eğer my_sind 180 ° 'nin katlarında kesin cevaplar veriyorsa +0.0 veya -0.0 (diğerinden daha fazla tercih etmek için net bir neden göremiyorum)." Bu şimdiye kadarki en yakın tartışma noktası. "En az şaşkınlık ilkesinin" her zaman geri dönmeyi teşvik ettiğini düşünüyorum +0.0, ancak -0.0bazı durumlarda (dışında x == +/-0.0) geri dönmek için zorlayıcı nedenler olup olmadığını görmek için bakıyorum .
chux - Monica

@chux: Bence katları için 180.0, bu değerler verildiğinde göreceli makine hassasiyetinin değerlerini gerçekten incelemeliyiz. Yani, o sayısal formatta temsil edilebilir farklı bir değer veren en küçük artış / azalış. Ardından, artı tarafına mı yoksa eksi tarafına mı düşeceğini görmek için bu değeri gerçek değerle karşılaştırın.
rwong

@rwong Fikir için teşekkürler. 90.0 katları derece , kesin sind(double degrees) ve cosd(double degrees)değer iade edilebilir: -1.0, +0.0, +1.0. Bu gönderi -0.0asla iade edilmelidir (sind dışında (-0.0)). Not: sind()yok değil basit kullanmak sin(x/360*M_PI)yaklaşım.
chux - Monica

3

Kütüphane +0'ı -0'dan ayırmaya çalışmaz. IEEE 754 bu ayrım hakkında biraz endişeleniyor ... [math.h] içindeki fonksiyonların hiçbir şeyin işareti hakkında endişelenmeden yazmak için yeterince zor olduğunu gördüm. - PJ Plauger, Standart C Kütüphanesi , 1992, sayfa 128.

Resmi olarak, trig fonksiyonları, C standardına uygun olarak sıfır işaretini döndürmelidir ... bu da davranışı tanımsız bırakır.

Tanımlanmamış davranış karşısında, en az şaşkınlık ilkesi , karşılık gelen işlevin davranışının çoğaltılmasını önerir math.h. Bu, haklı olarak kokuyor, karşılık gelen işlevin davranışlarından, math.hhataları tam olarak sıfır işaretine bağlı olan koda sokmanın bir yolu gibi kokuyor.


İçinde trigonometrik fonksiyonlar math.hbu işlevleri yalnızca gösterilebilen değerlerini alabilir olarak benzeri +/- pi / 2 veya +/- pi 0.0 verilen argümanlar dönmek yok yakın +/- vb pi / 2. Bu "yakın" değerler 0,0'a yakın sonuçlar döndürür. Std kütüphanesi trig fonksiyonları ( sin cos tan) herhangi bir giriş için (+/- 0.0 hariç) 0.0 (veya -0.0) döndürmediğinden, ancak my_sind (), my_cosd (), my_tand () 0.0 (veya -0.0) döndürebilir. çoğaltmak için 0.0 davranış yok.
chux - Monica

@chux öncül sin(-0.0)dönmelidir -0şüphelidir. IEEE standardının uygulama detayını trigonometrik bir prensip olarak ele alır. IEEE uygulamasında somutlaştırılan iki aralığın sınırı olarak sıfır genel bir matematiksel prensip olmasına rağmen, genel trigonometri içinde olmayan bu soyutlama seviyesinde gerçekleşir [dolayısıyla trigonometrik fonksiyonlarınızın geri döndüğü değişkenlik]. Olabilecek en iyi şey, keyfi bir kongre tanımlayabilmenizdir, ancak math.hsıfır işaretinden farklı olmamasından farklı olacaktır .
ben rudgers

Not: Ben demiyorum sin(-0.0)dönmelidir -0.0, ama bu my_sind(x)aynı olmalıdır sin(x)zaman xolduğu +/-0.0. IOW: önceki uygulamayı takip edin. Dahası, sorunun kendisi ne zaman x != 0.0yapılması gerektiği, daha my_sind(x)önce -0.0olduğu gibi geri dönmesi my_sind(180)vb. Belki cevabınız / yorumunuz bunu ele alır - ama ben görmedim.
chux - Monica

@chux Davranış tanımsızsa tanımsızdır. C tam da bu şekilde. Plauger yirmi yıl önce yazdığı zamana +0karşı endişe etmedi . Aradaki fark hakkında endişelenmenizin hangi sorunu çözdüğü açık değil. -0math.h
ben rudgers

1
İnşallah görüyorsunuz iyi uygulanmış sin(rad)bir değer için herhangi bir değer rad>0ve herhangi bir hassasiyetle 0.0pi irrasyonel olduğu için asla vermez . [Ref] (www.csee.umbc.edu/~phatak/645/supl/Ng-ArgReduction.pdf) Bununla birlikte my_sind(deg)tam bir verir 0.0(+ veya -) her çoklu 180.0değeri 0.0 doğru matematiksel sonuç olarak. "En az şaşkınlık ilkesi" bu durumlarda 0,0 döndürmeyi öneriyor. Sorum -0.0bu durumlarda hiç iade edilmelidir ?
chux - Monica
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.