Results 1 to 10 of 10

Thread: ใน java 0.1 บวกกัน 10 ครั้ง = 0.99... เรื่องที่บางคนอาจไม่รู้

  1. #1
    Junior Member
    Join Date
    Mar 2008
    Location
    KMITL
    Posts
    3


    คุณเชื่อหรือไม่ครับ ในภาษา java มี bug ?? หรือ code รูปแบบหนึ่ง ที่มีความแปลก

    โดย code จะเป็นลักษณะดังนี้



    class Cal
    {
    public static void main(String[] args)
    {
    double x = 0;

    for (int i=1;i<=10;i++)
    { x += 0.1;
    System.out.println("row"+i+" x = "+x);
    }

    }
    }

    [/b]
    อันนี้ผมทดลองเขียน code ง่ายๆ ขึ้นมาครับให้ทำการ + 0.1 ให้กับ x ซึ่งวน loop เท่ากับ 10 ครั้ง

    ค่าที่ควรจจะได้ค่าสุดท้ายนั้น ตามที่เราคิดควรจะเป็น 1.0 ใช่ใหมครับ แต่ผิดถนัด


    row1 x = 0.1
    row2 x = 0.2
    row3 x = 0.30000000000000004
    row4 x = 0.4
    row5 x = 0.5
    row6 x = 0.6
    row7 x = 0.7
    row8 x = 0.7999999999999999
    row9 x = 0.8999999999999999
    row10 x = 0.9999999999999999

    [/b]
    อันนี้เป็น output ที่เกิดจากการ run program ด้านบนครับ จะเห็นว่าได้ค่า = 0.99...

    เหตุผลที่แท้จริงนั้นผมเองก็ไม่ทราบครับ ท่านใดสามารถอธิบายเหตุการณ์นี้ได้ช่วยชี้แจ้งด้วยนะครับ


  2. #2
    Junior Member jaynarol's Avatar
    Join Date
    Oct 2007
    Location
    Thailand
    Posts
    14


    โอ้โห

    เพิ่งทราบเหมือนกันนะครับเนี่ย

    จิงๆผมไม่ค่อยได้เขียนjavascritpพวกมีทศนิยมซะด้วย

    ยังไม่เคยทดลองด้วยตัวเองเหมือนกัน

    แต่ผมคิดว่าน่าจะมีทางแก้อยู่นะครับ

    ยังไงก็รอผู้รู้มาตอบเองดีกว่า ไม่อยากตอบมั่วครับกลัวหน้าแตก อิอิ

  3. #3
    Junior Member
    Join Date
    Mar 2008
    Posts
    1


    สมัยที่ผมเรียนแมทอ่ะ คุณรู้ไหมว่า 1+1 ไม่ได้เท่ากับ 2 นะครับ

    มันได้ค่าประมาณ 1.999999999899ซ้ำ (ทางแมท เค้าอนุมานว่า เข้าใกล้ 2 ที่สุด บนเส้นจำนวน)

    ถ้าคิดโดยสมการแรกเริ่มมา จนถึงสุดท้ายนะครับ

    แต่ผมจำไม่ได้แล้วอ่ะ เลคเชอร์ก็ไม่รู้อยู่ไหนแล้ว (คำพูดเลยถูกลดความน่าเชื่อถือลงไป 89%)

    ลองเปลี่ยน type ของ x เป็น int ดู แล้วผลลัพธ์ มันเปลี่ยนมั๊ยครับ

    หรือว่าเหมือนเดิม

  4. #4
    Junior Member
    Join Date
    Mar 2008
    Posts
    0


    หรอครับ

    ผมก็เพิ่งรู้นะเนี่ย

    0.999999999มันก็เกือบจะ1.0และนะ

    อีกนิดนึง

  5. #5
    Junior Member
    Join Date
    Mar 2008
    Location
    KMITL
    Posts
    3


    การเปลี่ยน x เป็น int นั้นทำไม่ได้ครับ เนื่องจากเราใช้ 0.1 + กัน ซึ่งเป็นเลข ทศนิยม

    แต่ int เก็บเป็นจำนวนเต็ม

    แต่อย่างไรก็ตามผมได้ไปลองเปลี่ยนตัวแปร x เป้นชนิด float ได้ผลออกมาแปลกๆอีกแล้วครับ

    == float ==
    row1 x = 0.1
    row2 x = 0.2
    row3 x = 0.3
    row4 x = 0.4
    row5 x = 0.5
    row6 x = 0.6
    row7 x = 0.70000005
    row8 x = 0.8000001
    row9 x = 0.9000001
    row10 x = 1.0000001
    [/b]

  6. #6
    Junior Member jaynarol's Avatar
    Join Date
    Oct 2007
    Location
    Thailand
    Posts
    14


    อิอิ

    ผมว่านะครับถึงมันจะไม่เสถียร(มั้ง)

    แต่ก็เป็นทศนิยมหลักที่7-8โน่นแหละครับ

    ซึ่งโอกาศที่เราจะใช้มีน้อยมาก

    เพราะส่วนใหญ่ใช้กันแค่2หลัก

    คนส่วนใหญ่เลยไม่ค่อยกังวลมั้งครับ^^

    และถ้าเขาจะเขียนละเอียดขนาดนั้นก็อาจจะใช้ภาษาอื่นแล้วมั้งครับ

  7. #7
    Member spicydog's Avatar
    Join Date
    Aug 2007
    Location
    Thailand
    Posts
    41


    ถือซะว่า 0.99 ก็คือ lim เข้าใกล้ 1 ละกันครับ 5555
    ท่าทางโปรแกรมมันจะเมา
    [b]spicydog[/b]

  8. #8
    Junior Member
    Join Date
    Mar 2008
    Location
    KMITL
    Posts
    3


    คือที่ผมแสดง ต้องการให้เห็นถึงปัญหาเวลาเขียนโปรแกรมไงครับ เช้น

    for (int i=0; i<=1 ; i+=0.1 )
    {
    System.out.println("ChokBa")
    }
    [/b]
    มันจะวน 11 รอบแทนที่จะ 10 รอบอะครับ ^ ^

  9. #9


    เห็นมีแต่ปัญหา ขอเขียนวิธีแก้ละกัน
    1. อย่า ใช้ double/float ใน java ให้ใช้ BigDecimal แทน เพราะ java ไม่สามารถแทนค่าทศนิยมได้อย่างถูกต้อง
    2. อย่าใช้ == หรือ != กับ ทศนิยมในการเปรียบเทียบทศนิยมใน java แล้วใช้ Float.floatToIntBits (float) หรือ Double.doubleToLongBits (double) แทน หากใช้ == หรือ != เพราะมีความเป็นไปได้ที่ code จะทำงานผิดพลาด
    3. ใช้ BigDecimal กับ temporary variables และ convert ค่ากลับเป็น float/double เมื่อต้องการยัดมันลง database

  10. #10
    Senior Member
    Join Date
    Feb 2007
    Location
    Bangkok
    Posts
    118


    ผมว่าน่าจะเป็นเรื่องของ การกระทำกันในระดับบิตนะครับ ที่มันทำให้เกิด bug นี้ขึ้นมา
    เพราะว่า เลขทศนิยมในจาวานั้นจะประกอบกันด้วยสามส่วนด้วยกันคือ
    1. sign คือเครื่องหมาย + - ของตัวเลขนั้น
    2. mantissa คือ ความละเอียของตัวเลขนั้น
    3. exponent คือ จำนวนกำลังของสิบของตัวเลขนั้น
    ค่าของ exponent นั้นจะถูกเก็บลงในหน่วยความจำ 11 บิต ซึ่งเก็บตัวเลข แต่เพื่อให้สามารถเก็บได้ทั้งค่า + และ ค่า - จึงใช้การ bias 1023 หมายถึง ค่าของ exponent จะถูก + ด้วย 1023 ก่อนจัดลงในหน่วยความจำ แตถ้าเป็นตัว flot จะ bias ด้วย 127
    ซึ่ง double นั้นจะใช้
    sign 1 bit
    exponent 11 bit
    namtissa 52 bit
    bias 1023
    ซึ่งจากการกระทำตรงนี้นั้น เมื่อเกิดการ + กัน ของตัวเลขในระดับบิด จึงทำให้เกิดการผิดพลาดของข้อมูลไปเรื่อย ถ้าท่านอื่นมีความเห็นว่าไงช่วยอธิบายเสริมต่อทีนะครับ นี่เป็นความคิดส่วนตัวของผม ถ้าผิดพลาดก็ขออภัยด้วย

Similar Threads

  1. Replies: 12
    Last Post: 30-04-2010, 09:59 AM
  2. Replies: 3
    Last Post: 07-01-2010, 03:28 AM
  3. Java, Java, Java, Object-Oriented Problem Solving
    By Black_Phoenix in forum E-Book, Video หรือบทความทั่วไปด้าน Computer
    Replies: 0
    Last Post: 25-02-2008, 11:55 PM
  4. Replies: 0
    Last Post: 19-06-2007, 04:38 PM
  5. Replies: 5
    Last Post: 25-03-2007, 11:19 AM

Members who have read this thread : 0

Actions : (View-Readers)

There are no names to display.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •