Khi nào một hàm trig, với một đối số độ, trả về -0.0?


10

Trong việc tạo ra các chức năng trang điểm my_sind(d), my_cosd(d), my_tand(d), mà sử dụng một đối số mức độ chứ không phải là một radian và cung cấp câu trả lời chính xác ở bội số của 90, tôi nhận thấy rằng kết quả là đôi khi -0.0hơn 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()tan()thường trả về cùng một kết quả bằng không cho một đầu vào không có dấu đã cho. Nó có ý nghĩa my_sin()nên phù hợp sin()cho những đầu vào.

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

Câu hỏi đặt ra là : đối với những gì toàn bộ số non_zero_nnên / có thể kết quả bao giờ trở lại -0.0cho my_sind(180*non_zero_n), my_cosd(180*n + 180), my_tand(180*non_zero_n)?

Nó là đủ dễ dàng để mã để chỉ f(-0.0)sản xuất -0.0và được thực hiện với nó. Đơn giản tự hỏi nếu có bất kỳ lý do để thực hiện trở lại khác cho bất kỳ khác (khác không ) và tầm quan trọng của bảo hiểm dấu hiệu đó.f(x)-0.0x


Lưu ý: Đây không phải là một câu hỏi tại sao 0.0so với -0.0xảy ra. Đây không phải là lý do tại sao cos(machine_pi/4)không trở lại 0.0. Đây không phải là một câu hỏi làm thế nào để kiểm soát việc tạo ra 0.0hoặc -0.0. Tôi thấy nó tốt nhất như một câu hỏi thiết kế.

Câu trả lời:


4

Nguyên tắc thiết kế "ít bất ngờ nhất" gợi ý rằng chúng tôi tìm đến chức năng được thiết lập trước đó để được hướng dẫn. Trong trường hợp này, chức năng được thiết lập gần nhất được cung cấp bởi sinpivà các cospichức năng được giới thiệu trong IEEE Std 754-2008 (Tiêu chuẩn IEEE về Số học dấu phẩy động), phần 9. Các chức năng này không phải là một phần của tiêu chuẩn ISO C và ISO C ++ hiện tại, nhưng đã được tích hợp vào các thư viện toán học của các nền tảng lập trình khác nhau, ví dụ CUDA.

Các hàm này tính sin (πx) và cos (πx), trong đó phép nhân với π xảy ra ngầm bên trong hàm. tanpikhông được xác định, nhưng có thể, dựa trên tính tương đương toán học, được giả định để cung cấp chức năng theo tanpi(x) = sinpi(x) / cospi(x).

Bây giờ chúng ta có thể định nghĩa sind(x) = sinpi(x/180), cosd(x) = cospi(x/180), tand(x) = tanpi(x/180)một cách trực quan. Mục 9.1.2 của IEEE-754 giải thích việc xử lý các đối số đặc biệt cho sinpicospi. Đặc biệt:

sinPi (+ n) là +0 và sinPi (n) là −0 cho các số nguyên dương n. Điều này ngụ ý, trong các chế độ làm tròn thích hợp, sinPi (x) và −sinPi (x) là cùng một số (hoặc cả NaN) cho tất cả x. cosPi (n +) là +0 cho bất kỳ số nguyên n nào khi n + có thể biểu diễn.

Tiêu chuẩn IEEE 754-2008 không đưa ra lý do cho các yêu cầu được trích dẫn, tuy nhiên, một bản dự thảo ban đầu của phần có liên quan nêu rõ:

Nếu giá trị của hàm bằng 0, dấu của 0 này được xác định tốt nhất bằng cách xem xét sự mở rộng liên tục của hàm dấu của hàm toán học.

Sự lưu giữ của 754 Lưu trữ thư nhóm làm việc có thể mang lại những hiểu biết bổ sung, tôi chưa có thời gian để tìm hiểu về nó. Thực hiện sind(), cosd()tand()như được mô tả ở trên, sau đó chúng ta đến bảng các trường hợp ví dụ này:

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 () và tan () thường trả về cùng một kết quả zero cho một đầu vào zero đã cho

Nó có thể nói chung là đúng vì:

  • Tốc độ / độ chính xác . Đối với đôi đủ nhỏ, câu trả lời tốt nhất sin(x)x. Đó là, đối với các số nhỏ hơn khoảng 1.49e-8, gấp đôi gần nhất với sin của x thực sự là chính x (xem mã nguồn glibc cho sin () ).

  • Xử lý các trường hợp đặc biệt .

    Một vài phép toán số học đặc biệt bị ảnh hưởng bởi dấu 0; ví dụ "1/(+0) = +inf"nhưng "1/(-0) = -inf". Để giữ lại tính hữu dụng của nó, bit dấu phải truyền qua các phép toán số học nhất định theo các quy tắc xuất phát từ các xem xét liên tục.

    Việc triển khai các chức năng siêu việt cơ bản như sin (z) và tan (z) và nghịch đảo và các chất tương tự hyperbol của chúng, mặc dù không được quy định bởi các tiêu chuẩn của IEEE, dự kiến ​​sẽ tuân theo các quy tắc tương tự. Việc thực hiện sin(z) dự kiến ​​sẽ tái tạo dấu hiệu z cũng như giá trị của nó tạiz = ±O .

    ( Cắt giảm chi phí cho các chức năng cơ bản phức tạp hoặc nhiều phiền toái về Bit ký hiệu không có gì của W. Kahan)

    Số 0 được ký âm phủ định khái niệm phân tích toán học về việc tiếp cận 0 từ bên dưới dưới dạng giới hạn một phía (xem xét 1 / sin(x): dấu của số 0 tạo ra sự khác biệt rất lớn).

BIÊN TẬP

Xem xét điểm thứ hai tôi sẽ viết my_sindđể:

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

Tiêu chuẩn C mới nhất (F.10.1.6 sinvà F.10.1.7 tan, các triển khai có số 0 được ký), xác định rằng nếu đối số là ±0, nó được trả về không thay đổi .

CHỈNH SỬA 2

Đối với các giá trị khác tôi nghĩ đó là vấn đề gần đúng. Cho 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

Vì vậy, nếu my_sindcung cấp câu trả lời chính xác ở bội số 180 °, nó có thể trả về +0.0hoặc -0.0(tôi không thấy lý do rõ ràng để thích cái này hơn cái kia).

Nếu my_sindsử dụng một số phép tính gần đúng (ví dụ: degree * M_PI / 180.0công thức chuyển đổi), thì nên xem xét cách tiếp cận các giá trị tới hạn.


Suy nghĩ của bạn liên quan là sind(180), sind(-180), sind(360), sind(-360),...gì?
chux - Tái lập lại

Cảm ơn các cập nhật. Có lẽ bài viết của tôi không rõ ràng. Câu hỏi chính là my_trig(x)bao giờ nên trở lại -0.0khi |x|không 0.0?
chux - Phục hồi Monica

Cảm ơn vì "Vì vậy, nếu my_sind cung cấp câu trả lời chính xác ở bội số 180 °, nó có thể trả về +0.0 hoặc -0.0 (Tôi không thấy lý do rõ ràng để thích cái này hơn cái kia)." Đó là điểm thảo luận gần nhất cho đến nay. Tôi nghĩ rằng "nguyên tắc ít ngạc nhiên nhất" khuyến khích luôn luôn quay trở lại +0.0, nhưng đang tìm xem liệu có lý do thuyết phục nào để quay lại -0.0trong một số tình huống (ngoài lý do x == +/-0.0).
chux - Tái lập Monica

@chux: Tôi nghĩ rằng đối với bội số của 180.0, người ta thực sự phải kiểm tra các giá trị của độ chính xác của máy tương đối với các giá trị đó. Đó là, mức tăng / giảm nhỏ nhất mang lại giá trị đại diện khác nhau trong định dạng số đó. Sau đó, so sánh giá trị đó với giá trị thực để xem liệu nó sẽ nằm ở phía cộng hay trừ.
rwong

@rwong Cảm ơn ý kiến. Bội số 90,0 độ , chính xác sind(double degrees)cosd(double degrees)giá trị có thể được trả về : -1.0, +0.0, +1.0. Bài đăng này là về -0.0bao giờ nên được trả lại (ngoài sind (-0.0)). Lưu ý: sind()không không sử dụng đơn giản sin(x/360*M_PI)tiếp cận.
chux - Tái lập Monica

3

Thư viện không cố phân biệt +0 với -0. IEEE 754 lo lắng khá nhiều về sự khác biệt này ... Tôi thấy các hàm [trong math.h] khá khó để viết mà không băn khoăn về dấu hiệu của hư vô. - PJ Plauger, Thư viện C tiêu chuẩn , 1992, trang 128.

Chính thức, các hàm trig sẽ trả về dấu bằng 0 phù hợp với tiêu chuẩn C ... khiến hành vi không được xác định.

Khi đối mặt với hành vi không xác định, nguyên tắc ít ngạc nhiên nhất cho thấy việc nhân đôi hành vi của chức năng tương ứng từ đó math.h. Điều này có mùi hợp lý, trong khi chuyển hướng từ hành vi của hàm tương ứng math.hcó mùi giống như một cách để đưa lỗi vào chính xác mã phụ thuộc vào dấu bằng không.


Các hàm trig math.hkhông trả về 0,0 khi các đối số đã cho như +/- pi / 2 hoặc +/- pi vì các hàm này chỉ có thể nhận các giá trị đại diện gần +/- pi / 2, v.v. Các giá trị "gần" này trả về kết quả gần 0,0. Vì các hàm trig của thư viện std ( sin cos tan) không trả về 0,0 (hoặc -0,0) cho bất kỳ đầu vào nào (ngoại trừ +/- 0,0), nhưng my_sind (), my_cosd (), my_tand () có thể trả về 0,0 (hoặc -0.0) không có hành vi 0,0 để nhân đôi.
chux - Phục hồi Monica

@chux Tiền đề sin(-0.0)nên quay lại -0là nghi ngờ. Nó coi một chi tiết thực hiện của tiêu chuẩn IEEE là một nguyên tắc lượng giác. Mặc dù có một nguyên tắc toán học chung bằng 0 là giới hạn của hai khoảng thời gian được thể hiện trong triển khai IEEE, nhưng nó xảy ra ở mức độ trừu tượng đó không nằm trong lượng giác chung [do đó có thể thay đổi hàm lượng giác của bạn trở lại]. Điều tốt nhất có thể xảy ra là bạn có thể xác định một quy ước tùy ý, nhưng nó sẽ khác nhau từ math.hsự không quan tâm đến dấu hiệu của số không.
ben rudgers

Lưu ý: Tôi không gợi ý sin(-0.0)nên trả lại -0.0, nhưng điều đó my_sind(x)sẽ phù hợp sin(x)khi x+/-0.0. IOW: làm theo thực hành trước. Hơn nữa, bản thân câu hỏi là nhiều hơn về những gì cần làm khi nào x != 0.0, my_sind(x)bao giờ nên trở lại -0.0như trong my_sind(180), vv? Có thể câu trả lời / nhận xét của bạn giải quyết điều đó - nhưng tôi chưa thấy điều đó.
chux - Tái lập lại

@chux Nếu hành vi không được xác định, thì nó không xác định. Đó chỉ là cách của C. Plauger đã không lo lắng +0so với -0khi ông viết math.hhai mươi năm trước. Tôi không rõ vấn đề gì khiến bạn băn khoăn về sự khác biệt đang giải quyết.
ben rudgers

1
Hy vọng rằng bạn thấy rằng để thực hiện tốt sin(rad)cho bất kỳ giá trị rad>0và độ chính xác nào sẽ không bao giờ mang lại 0.0vì pi là không hợp lý. [Ref] (www.csee.umbc.edu/~phatak/645/supl/Ng-ArgRedraction.pdf) Tuy nhiên, kết my_sind(deg)quả chính xác 0.0(hoặc + hoặc -) mỗi bội số của 180.0giá trị 0,0 là kết quả toán học chính xác. "Nguyên tắc ít ngạc nhiên nhất" đề nghị trả lại 0,0 trong những trường hợp này. Câu hỏi của tôi là -0.0bao giờ nên được trả lại trong những trường hợp này?
chux - Phục hồi Monica
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.