Điểm tròn


13

Số hiệu dấu phẩy động IEEE-754 <1 (nghĩa là được tạo bằng bộ tạo số ngẫu nhiên tạo ra một số> = 0,0 và <1.0) có thể được nhân với một số nguyên (ở dạng dấu phẩy động) để có được một số bằng hoặc lớn hơn số nguyên đó do làm tròn?

I E

double r = random() ; // generates a floating point number in [0, 1)
double n = some_int ;
if (n * r >= n) {
    print 'Rounding Happened' ;
}

Điều này có thể tương đương với việc nói rằng có tồn tại N và R sao cho nếu R là số lớn nhất nhỏ hơn 1 có thể được biểu thị trong IEEE-754 thì N * R> = N (trong đó * và> = là phù hợp với IEEE- 754 nhà khai thác)

Điều này xuất phát từ câu hỏi này dựa trên tài liệu nàyhàm ngẫu nhiên postgresql


Bạn có thể nói bất cứ điều gì về phạm vi của N, tức là nó có đủ nhỏ để được thể hiện chính xác trong độ chính xác kép của IEEE-754 không?
Pedro

@Pedro Trong trường hợp cụ thể này, vâng, nó sẽ là một số nguyên nhỏ - tức là 10. Tôi giả sử bạn đang nói rằng nếu N là một số nguyên rất lớn với một số lượng rất lớn các chữ số có nghĩa thì nó có thể không được biểu diễn chính xác?
Cade Roux

Chính xác, nếu , sau đó f l ( R × f l ( N ) ) có thể lớn hơn R N . fl(N)>Nfl(R×fl(N))RN
Pedro

Câu trả lời:


8

Giả sử từ tròn đến gần nhất và , thì N R < N luôn. (Cẩn thận không chuyển đổi một số nguyên quá lớn.)N>0N*R<N

Đặt , trong đó c [ 1 , 2 ) là số có nghĩa và q là số mũ nguyên. Đặt 1 - 2 - s = R và rút ra giới hạnc2-q= =Nc[1,2)q1-2-S= =R

NR=c2q(12s)c2q2qs,

với đẳng thức khi và chỉ khi . Phía bên tay phải nhỏ hơn N và, vì 2 - q - s chính xác là 0,5 đơn vị ở vị trí cuối cùng của N , nên c = 12 - q - 2 - q - s là đại diện chính xác (vì N là bình thường và không phải là bình thường nhỏ nhất), hoặc c > 1 , và làm tròn gần nhất là xuống. Trong cả hai trường hợp, N * R nhỏ hơn Nc=1N2qs0.5Nc=12q2qsNc>1NRN.


Làm tròn lên có thể gây ra một vấn đề, không phải là nó nên được chọn trong trường hợp người dùng không nghi ngờ. Đây là một số C99 in "0\n1\n"trên máy của tôi.

#include <fenv.h>
#include <math.h>
#include <stdio.h>

int main(void) {
    double n = 10;
    double r = nextafter(1, 0);
    printf("%d\n", n == (n * r));
    fesetround(FE_UPWARD);
    printf("%d\n", n == (n * r));
}

Tôi xin lỗi, tôi hơi chậm trong những ngày này - Tôi gặp khó khăn khi có một phần của sự bất bình đẳng
c2q2s2qs
Cade Roux

2qs

Cảm ơn, tôi không chắc có thiếu một bước nữa không.
Cade Roux
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.