12A1 K06-09 LÊ TRUNG KIÊN

Bạn có muốn phản ứng với tin nhắn này? Vui lòng đăng ký diễn đàn trong một vài cú nhấp chuột hoặc đăng nhập để tiếp tục.
12A1 K06-09 LÊ TRUNG KIÊN

WE ARE TOGETHER..!! NOTHING


    bai tap c++

    Admin
    Admin
    Admin
    Admin


    Tổng số bài gửi : 71
    Points : 184
    Join date : 16/01/2010
    Age : 32
    Đến từ : KingDom-Hoi tu thang hoa.!

    bai tap c++ Empty bai tap c++

    Bài gửi  Admin Sun Apr 11, 2010 11:12 pm

    Khảo sát số chấm động của các ngôn ngữ lập trình trên nền kiến trúc x86
    Mục đích
     Tìm hiểu số chấm động trong các ngôn ngữ lập trình trên nền kiến trúc x86
     Hiểu rõ hơn về cách tổ chức số chấm động
    Tóm tắt lý thuyết
    Hầu hết các ngôn ngữ lập trình trên nền kiến trúc x86 như Assembly, C/C++, Java, VB, C#,… đều sử dụng chuẩn số chấm động IEEE 754 để biểu diễn số chấm động. Trong đó, chuẩn số chấm động 32-bit (single – chính xác đơn) và chuẩn 64-bit (double – chính xác kép) được sử dụng phổ biến nhất. Ví dụ trong ngôn ngữ C, kiểu float sử dụng số chấm động 32-bit, kiểu double sử dụng số chấm động 64-bit.
    Bài tập
    Bài 1. Viết chương trình nhập vào số chấm động. Hãy xuất ra biểu diễn nhị phân từng thành phần (dấu, phần mũ, phần trị) của số chấm động vừa nhập
    Ví dụ:
    Nhập vào số chấm động (32-bit): 6
    Biểu diễn nhị phân tương ứng: 0 10000001 10000000000000000000000
    Nhập vào số chấm động (32-bit): -12.625
    Biểu diễn nhị phân tương ứng: 1 10000010 10010100000000000000000
    Nhập vào số chấm động (32-bit): 0.1015625
    Biểu diễn nhị phân tương ứng: 0 01111011 10100000000000000000000
    Nhập vào số chấm động (32-bit): 0.1
    Biểu diễn nhị phân tương ứng: 0 01111011 10011001100110011001101
    Nhập vào số chấm động (32-bit): 0
    Biểu diễn nhị phân tương ứng: 0 00000000 00000000000000000000000
    Hướng dẫn:
    - Viết hàm dumpFloat(float *p) trên ngôn ngữ C++ cho phép xem các bit của một biến kiểu float
    o Ví dụ trong chương trình có khai báo biến float x thì khi gọi dumpFloat(&x) sẽ in ra màn hình biểu diễn nhị phân của giá trị đang lưu trong x, trong đó chỉ rõ phần nào là exponent, phần nào là significand
    o Lưu ý: nên dùng các phép toán trên bit để lấy nội dung các bi và in ra chứ không thực hiện việc chuyển đổi thủ công

    Bài 2. Viết chương trình nhập vào biểu diễn nhị phân của số chấm động. Hãy xuất ra biểu diễn thập phân tương ứng
    Ví dụ:
    Dãy nhị phân: 0 10001000 01101100001000000000000
    Số chấm động (single) tương ứng: 728.25
    Dãy nhị phân: 1 01000110 01101011000000000000000
    Số chấm động (single) tương ứng: -9.83913471531 × 10-18
    Dãy nhị phân: 0 01111011 10011001100110011001101
    Số chấm động (single) tương ứng: 0.1
    Dãy nhị phân: 0 11111111 00000000000000000000000
    Số chấm động (single) tương ứng: +
    Dãy nhị phân: 0 11111111 10000000000000000000000
    Số chấm động (single) tương ứng: NaN
    Hướng dẫn:
    - Viết hàm forceFloat(float *p, char *s) trên ngôn ngữ C++ cho phép ghi các bit cào một vùng nhớ kiểu float
    o Ví dụ trong chương trình có khai báo biến float x thì khi gọi forceFloat(&x, “10011”), 5 bit cao nhất (LSB) của vùng bộ nhớ 32 bit chiếm bởi x sẽ bị ghi giá trị lần lượt là 1,0,0,1,1 còn các bit còn lại sẽ được gán giá trị 0. Giả định chuỗi s chỉ chứa các ký tự 0 hoặc 1 và có độ dài không quá 32

    Bài 3: Dùng 2 hàm đã viết để khảo sát các câu hỏi:
    - 1.3E+20 có biểu diễn nhị phân ra sao
    - Số float nhỏ nhất lớn hơn 0 là số nào? Biểu diễn nhị phân của nó?
    - Những trường hợp nào tạo ra các số đặc biệt (kiểu float) (viết chương trình thử nghiệm và giải thích kết quả):
    o Số vô cùng (inf)
    o Số báo lỗi NaN
    o Ví dụ: X – (+), (+) – (+), X/0, 0/0, /, sqrt(X) với X<0,…(Tham khảo thêm một số trường hợp trong slide 13 bài giảng Số chấm động)

    Bài 4: Khảo sát các trường hợp sau đây (viết chương trình thử nghiệm và giải thích kết quả):
    1. Chuyển đổi float -> int -> float.Kết quả như ban đầu ?
    2. Chuyển đổi int -> float -> int. Kết quả như ban đầu ?
    3. Phép cộng số chấm động có tính kết hợp ?
    (x+y)+z = x+(y+z)
    Với i là biến kiểu int, f là biến kiểu float
    4. i = (int) (3.14159 * f);
    5. f = f + (float) i;
    6. if (i == (int)((float) i)) { printf(“true”); }
    7. if (i == (int)((double) i)) { printf(“true”); }
    8. if (f == (float)((int) f)) { printf(“true”); }
    9. if (f == (double)((int) f)) { printf(“true”); }
    Hướng dẫn thuật toán
    Cách 1: Thực hiện theo các thuật toán
    Thuật toán: chuyển từ giá trị số chấm động sang biểu nhị phân.
    Ví dụ: chuyển -12.625 sang biểu diễn nhị phân
    1. Chuyển phần trị sang dạng nhị phân.
    a. Phần nguyên: theo thuật toán chuyển từ số thập phân sang nhị phân
    1210 = 11002
    b. Phần thập phân: Lặp lại việc nhân phần thập phân với 2 cho tới khi phần thập phân bằng 0 (hoặc đủ số bit phần trị). Tại mỗi bước nhân, sẽ phát sinh 1 bit tùy thuộc vào phần nguyên của kết quả phép nhân
    0.625  2 = 1.25  1
    0.25  2 = 0.5  0
    0.5  2 = 1.0  1
    Như vậy, biểu diễn nhị phân của phần trị:
    1100.101
    2. Chuẩn hóa
    1100.101 = 1.100101  23
    3. Điền các bit vào các trường theo chuẩn:
     Dấu: số âm nên bit dấu
    S = 1
     Phần mũ: cộng phần mũ của 2 (tìm được sau bước chuẩn hóa) với phần bias (2k-1-1)
    E = 310 + 12710 = 13010 = 100000102 (với bias = 28-1-1 = 127)
     Phần trị: thêm bit 0 vào bên phải cho đủ số bit phần trị
    M = 10010100000000000000000
    Như vậy, biểu diễn nhị phân của số chấm động -12.625 là
    1 10000010 10010100000000000000000

    Thuật toán: chuyển từ biểu diễn nhị phân của số chấm động sang biểu diễn thập phân
    Ví dụ: chuyển dãy bit 01000100001101100001000000000000 sang biểu diễn thập phân
    1. Chia thành 3 thành thành phần
    S = 0
    E = 10001000
    M = 01101100001000000000000
    2. Tính phần mũ: đổi dãy nhị phân thành số thập phân rồi trừ cho bias (2k-1-1)
    E = 100010002 = 13610 = 136-127 = 9
    3. Tính phần trị: phục hồi bit 1 ở phần nguyên và loại bỏ các bit 0 thừa ở cuối
    M = 1.01101100001
    4. Kết hơp phần trị với phần mũ:
    1.01101100001  29 = 1011011000.01
    Nếu trị tuyệt đối của phần mũ quá lớn, không thể kết hợp với phần trị như trên, thì có thể thực hiện tính giá trị của phần mũ rồi nhân với phần trị sẽ cho kết quả gần đúng
    5. Chuyển dãy nhị phân thành giá trị số chấm động tương ứng
    Lũy thừa 29 28 27 26 25 24 23 22 21 20 2-1 2-2
    Giá trị tương ứng 512 256 128 64 32 16 8 4 2 1 0.5 0.25
    Bits 1 0 1 1 0 1 1 0 0 0 . 0 1
    Giá trị tính được 512 + 128 + 64 + 16 + 8 + 0.25 = 728.25
    6. Thêm dấu:
    S = 0 nên là số dương
    Như vậy, giá trị thập phân tương ứng với dãy bit 01000100001101100001000000000000 là
    728.25

    Cách 2:
    Dựa vào bản chất lưu trữ nhị phân, có thể dễ dàng xuất dạng biểu diễn nhị phân của số chấm động hay chuyển dãy bit biểu diễn thành các giá trị lưu trữ tương ứng dựa vào các thao tác luận lý AND, OR, SHIFT LEFT, SHIFT RIGHT,…
    Chú ý:
    Không thể thực hiện các thao tác luận lý trực tiếp trên số thực
    float x;
    x >> 1;  báo lỗi
    Nên, cần lấy con trỏ tới vùng nhớ chứa số thực. Nhưng…
    long *p = &x;  báo lỗi
    Do đó, cần thực hiện ép kiểu như sau:
    long *p = (long *)&x;
    Và thực hiện các thao tác luận lý:
    *p >> 1;
    Mở rộng
    Mô phỏng một số phép toán trên số chấm động: cộng, trừ, nhân, chia

      Hôm nay: Thu May 09, 2024 8:52 pm