2010-10-18 31 views
9

Tôi đã được giao nhiệm vụ sử dụng java để tạo ra một bảng Sin, tuy nhiên tôi dường như nhận được một số kết quả rất lạ đối với một số giá trị của đầu vào. Tôi đang sử dụng dưới đâyHành vi lạ của Java với Sin và ToRadians

System.out.println("| sin(" + currentPoint + ") = " + Math.sin(Math.toRadians(currentPoint))); 

đâu (int) currentPoint là một giá trị trong độ (ví dụ 90)

Đây là những kết quả tôi thấy lạ

| sin(360) = -2.4492935982947064E-16 
| sin(180) = 1.2246467991473532E-16 
| sin(150) = 0.49999999999999994 
| sin(120) = 0.8660254037844387 

Mong

sin(360) = 0 
sin(180) = 0 
sin(150) = 0.5 
sin(120) = 0.866025404 

Tôi có thiếu gì đó không?

+1

Theo [google] (http://www.google .com/search? sourceid = chrome & ie = UTF-8 & q = sin + 360 + độ), 'sin (360 độ)' là trong thực tế '0'. Bạn có chắc chắn bạn có nghĩa là sin? –

+1

kết quả mong đợi của bạn sẽ diễn giải các giá trị dưới dạng radian, trong khi đó trong chương trình bạn đang xem xét chúng dưới dạng các phép đo độ. –

+1

Mã của bạn là chính xác, kỳ vọng là sai. – Ishtar

Trả lời

7

Bạn đang làm việc với số dấu chấm động, tìm kiếm câu trả lời chính xác sẽ không làm việc cho tất cả các giá trị. Hãy xem What Every Computer Scientist Should Know About Floating-Point Arithmetic. Bạn muốn các bài kiểm tra của bạn tương đương với kỳ vọng của bạn trong một số vùng đồng bằng. Lưu ý rằng các câu trả lời bạn nhận được khá gần. Nó thể hiện giá trị trong các bit đang cắn bạn.

Từ liên kết:

Nặn vô cùng nhiều số thực thành một số hữu hạn các bit yêu cầu một đại diện tương đối. Mặc dù có vô số số nguyên, trong hầu hết các chương trình, kết quả của phép tính nguyên có thể được lưu trữ trong 32 bit. Ngược lại, với bất kỳ số bit cố định nào, hầu hết các phép tính với số thực sẽ tạo ra các đại lượng không thể được biểu diễn chính xác bằng cách sử dụng nhiều bit đó. Do đó, kết quả của phép tính dấu chấm động thường phải được làm tròn để phù hợp với biểu diễn hữu hạn của nó. Lỗi làm tròn này là tính năng đặc trưng của tính toán dấu phẩy động.

2

Nếu mã của bạn là System.out.println("| sin(" + currentPoint + ") = " + Math.sin(currentPoint)); bạn mong chờ này:

sin(360) = 0.958915723 
sin(180) = -0.801152636 
sin(150) = -0.71487643 
sin(120) = 0.580611184

Nói cách khác, sin của 360 radian là 0,9589, nhưng sin của 360 độ 0.

EDIT:
Lý do bạn thấy kết quả không mong muốn chỉ là do thiếu tính chính xác trong các tính toán. Nếu bạn chỉ định dạng kết quả để chúng có ít chữ số thập phân hơn, số làm tròn sẽ xử lý nó. Làm một cái gì đó như thế này:

System.out.printf("| sin(%d) = %.7f\n", currentPoint, Math.sin(Math.toRadians(currentPoint)));

Sau đó, bạn sẽ nhận được kết quả gần gũi hơn với những gì bạn mong đợi.

+0

Tôi không có lựa chọn nào trong số này ..? –

+0

Pez: Kết quả của bạn là chính xác, chúng chỉ được định dạng kém. – Gabe

1

Áp phích ở trên là đúng. Các giá trị chính xác bạn đang mong đợi là:

Sin (360 độ) = 0 Sin (180 độ) = 0 Sin (150 độ) = 0,5 Sin (120 độ) = .866

Các mã đang trả về câu trả lời đúng. Họ chỉ cần được làm tròn. Hãy thử điều này:

System.out.printf("%s%.3f","| sin(" + currentPoint + ") = ", (Math.sin(Math.toRadians(currentPoint)))); 

Bạn có thể thay đổi giá trị .3f thành các số khác nhau nếu bạn muốn cải thiện hoặc giảm độ chính xác thập phân.

Vì một số lý do, nó hiển thị tội lỗi 360 là -0,00. Tôi chắc chắn có một giải pháp thanh lịch hơn, nhưng điều này sẽ làm việc.

CHỈNH SỬA: Bị đánh số giây. Sử dụng mã ở trên của tôi, nó dễ đọc hơn.

0

Dưới đây là mô tả API của phương pháp Math.sin. Lưu ý phần trong dấu hoa thị. Tôi sẽ đặt cược rằng sự khác biệt giữa kết quả mong đợi của bạn và khi bạn nhận được là lỗi của tính toán điểm nổi hoặc các vấn đề làm tròn.

tội

public static double sin (đôi một)

Returns the trigonometric sine of an angle. Special cases: 

    * If the argument is NaN or an infinity, then the result is NaN. 
    * If the argument is zero, then the result is a zero with the 

cùng dấu hiệu như là đối số.

A result must be within 1 **ulp** of the correctly rounded result. Results 

phải bán đơn điệu.

Parameters: 
    a - an angle, in radians. 
Returns: 
    the sine of the argument. 
1

Cũng lưu ý rằng Math.PI, là một giá trị kép, không phải là PI, nhưng chỉ xấp xỉ PI và Math.sin (Math.PI) mang lại cho bạn giá trị gấp đôi gần nhất với thực tế giá trị toán học của tội lỗi (Math.PI).

2

Kết quả của bạn là chính xác ... cho xấp xỉ thử này ...

result=Math.sin(Math.toRadians(value)); 
    result=format(result); 


    private double format(double value) { 
      return (double)Math.round(value * 1000000)/1000000; //you can change this to round up the value(for two position use 100...) 
     } 
2

Như đã đề cập ở trên nó không phải là một lỗi, chỉ là aproximation điểm số học nổi máy tính.

Để có được câu trả lời mong đợi, như sin() & cos() là giữa -1, 0, +1, cố gắng thêm 1 vòng nó vào accurancy cần thiết và trừ đi 1.

x = round15(Math.sin(toRad(angle))+1)-1; 

nơi round15 được định nghĩa

public double round15(double x){ 
    DecimalFormat twoDForm = new DecimalFormat("0.##############E0"); 
    String str = twoDForm.format(x); 
    return Double.valueOf(str); 
} 

Nó làm việc cho tôi, hy vọng các độc giả tương lai thích nó.

0

Bạn phải chuyển đổi góc thành radian như thế này

Math.sin (Math.toRadians (90)) và kết quả phải là 1