------------------------------------------------------------------------------------------------------------
                      [BUG/PRB.] VFP 9.0 FIX - ADJUST THE PRECISION OF THE FLOATING-POINT NUMBERS FOR THE STR() FUNCTION
                                 January 2024
                 ------------------------------------------------------------------------------------------------------------
                                     CCB



1. BUG:

     There is a test program:

     *PROC teststrfunction

     ?STR(1.154985,8,2) && Displays 1.15
     ?STR(1.154995,8,2) && Displays 1.16
     WAIT

     RETURN

     * END OF PROC TESTSTRFUNCTION.

     We think they will display 1.15, but:
     ?STR(1.154995,8,2) && Displays 1.16


2. CAUSE:

     When VFP 9.0 and earlier versions calculate STR(1.154995,8,2),
     it will adjust the precision of the nExpression paramater with the nDecimalPlaces paramater:

         1. 1549 9499 9999 9999 940
     +   0. 0000 0500 0000 0000 0 (n=2, eps = 0.5*10^(-(n+3)) = 5.0000000000000004090e-06)
     ----------------------------
         1. 1550 0000 0000 0000 270

     ROUND(1.1550000000000000270,2) = 1.16

     So STR(1.154995,8,2) = "1.16".

     When VFP Advanced calculates STR(1.154995,8,2),
     if the number of decimal places of the nExpression paramater is greater than the nDecimalPlaces paramater,
     it will adjust the precision of the nExpression paramater with the number of decimal places of the nExpression paramater:

         1. 1549 9499 9999 9999 940
     +   0. 0000 0000 0500 0000 0 (n=6, eps = 0.5*10^(-(n+3)) = 5.0000000000000003120e-10)
     ----------------------------
         1. 1549 9500 0500 0000 350

     ROUND(1.1549950005000000350,2) = 1.15

     So STR(1.154995,8,2) = "1.15".

     When VFP (VFP Advanced, VFP 9.0 and earlier versions) calculate TRANSFORM(1.154995),
     it will adjust the precision of the nExpression paramater with the number of decimal places of the nExpression paramater,
     and then calculate ROUND(1.154995,6) = 1.154995,
     and then transform it with the format code "#.######",
     so TRANSFORM(1.154995) = "1.154995".

     So there is no the bug for the TRANSFORM() function.


3. RESOLUTION:

     We can write some code to fix the BUG.

     Fun53ead3 :: ; proc near
             push ebp                                                        ;0x0053ead3 :        55
             mov ebp , esp                                                   ;0x0053ead4 :        8bec
             sub esp , 0110h                                                 ;0x0053ead6 :        81ec10010000
             fld qword ptr [ Data91fbc8 ]                                    ;0x0053eadc :        dd05c8fb9100
             mov eax ,  dword ptr [ Data937090 ]                             ;0x0053eae2 :        a190709300
             fld qword ptr [ ebp + 20 ]                                      ;0x0053eae7 :        dd4514
             push ebx                                                        ;0x0053eaea :        53
             push esi                                                        ;0x0053eaeb :        56
             fucompp                                                         ;0x0053eaec :        dae9
             push edi                                                        ;0x0053eaee :        57
             mov edi , ecx                                                   ;0x0053eaef :        8bf9
             mov  ecx , dword ptr [ ebp + 26 ]                               ;0x0053eaf1 :        8b4d1a
             shr ecx , 04h                                                   ;0x0053eaf4 :        c1e904
             mov  dword ptr [ ebp - 8 ] , eax                                ;0x0053eaf7 :        8945f8
             fstsw ax                                                        ;0x0053eafa :        dfe0
             and ecx , 07FFh                                                 ;0x0053eafc :        81e1ff070000
             sub ecx , 03FFh                                                 ;0x0053eb02 :        81e9ff030000
             test  byte ptr ah , 044h                                        ;0x0053eb08 :        f6c444
             jnp Label53eb1d                                                 ;0x0053eb0b :        7b10
             mov eax , ecx                                                   ;0x0053eb0d :        8bc1
             cdq                                                             ;0x0053eb0f :        99
             xor eax , edx                                                   ;0x0053eb10 :        33c2
             sub eax , edx                                                   ;0x0053eb12 :        2bc2
             cmp eax , 03Fh                                                  ;0x0053eb14 :        83f83f
             jnl Label59adea                                                 ;0x0053eb17 :        0f8dcdc20500

     Label53eb1d ::
             pushd 012h                                                      ;0x0053eb1d :        6a12
             pop edx                                                         ;0x0053eb1f :        5a
             cmp edi , edx                                                   ;0x0053eb20 :        3bfa
             jnl Label53eb26                                                 ;0x0053eb22 :        7d02
             mov edx , edi                                                   ;0x0053eb24 :        8bd7


     ;
     ;                 -------------------------------------------------------------------------------------------------
     ;                      VFP 9.0 FIX - ADJUST THE PRECISION OF THE FLOATING-POINT NUMBERS FOR THE STR() FUNCTION
     ;                                November 2019
     ;                 -------------------------------------------------------------------------------------------------
     ;                                     CCB
     ;
     ; Adjust the precision of the floating-point numbers for the STR() function.
     ;
     ; 2019/11/8, by ccb
     ;

             cmp dword ptr vfpa_sys9026_data,00h
             je Label53eb26
             cmp dword ptr [ esp + 120h ] , offset Label4ff6af ;; Label4ff587 ..
             jne Label53eb26
             cmp byte ptr [ebx],04Eh
             jne Label53eb26
             cmp edx,dword ptr [ebx+08h]
             jae Label53eb26
             mov edx,dword ptr [ebx+08h]


     Label53eb26 ::
             lea ecx ,  dword ptr [ ebp + 20 ]                               ;0x0053eb26 :        8d4d14
             call Fun53e46a                                                  ;0x0053eb29 :        e83cf9ffff

     Label53eb2e ::
             fld qword ptr [ ebp + 20 ]                                      ;0x0053eb2e :        dd4514
             push ecx                                                        ;0x0053eb31 :        51
             push ecx                                                        ;0x0053eb32 :        51
             fstp qword ptr [ esp ]                                          ;0x0053eb33 :        dd1c24
             pushd 01h                                                       ;0x0053eb36 :        6a01
             lea eax ,  dword ptr [ ebp + 0FFFFFEF4h ]                       ;0x0053eb38 :        8d85f4feffff
             push eax                                                        ;0x0053eb3e :        50
             push edi                                                        ;0x0053eb3f :        57
             call Fun53e49b                                                  ;0x0053eb40 :        e856f9ffff
             mov  esi , dword ptr [ ebp + 12 ]                               ;0x0053eb45 :        8b750c
             mov ebx , eax                                                   ;0x0053eb48 :        8bd8
             sub esi , ebx                                                   ;0x0053eb4a :        2bf3
             je Label4e9c37                                                  ;0x0053eb4c :        0f84e5b0faff
             test esi , esi                                                  ;0x0053eb52 :        85f6
             jle Label4a5e90                                                 ;0x0053eb54 :        0f8e3673f6ff
             mov  edi , dword ptr [ ebp + 8 ]                                ;0x0053eb5a :        8b7d08
             mov ecx , esi                                                   ;0x0053eb5d :        8bce
             mov edx , ecx                                                   ;0x0053eb5f :        8bd1
             shr ecx , 02h                                                   ;0x0053eb61 :        c1e902
             mov eax , 020202020h                                            ;0x0053eb64 :        b820202020
             rep stosd                                                       ;0x0053eb69 :        f3ab
             mov ecx , edx                                                   ;0x0053eb6b :        8bca
             and ecx , 03h                                                   ;0x0053eb6d :        83e103
             rep stosb                                                       ;0x0053eb70 :        f3aa
             mov  edi , dword ptr [ ebp + 8 ]                                ;0x0053eb72 :        8b7d08
             push ebx                                                        ;0x0053eb75 :        53
             lea ecx ,  dword ptr [ edi + esi ]                              ;0x0053eb76 :        8d0c37
             lea edx ,  dword ptr [ ebp + 0FFFFFEF4h ]                       ;0x0053eb79 :        8d95f4feffff
             call Fun42c19b                                                  ;0x0053eb7f :        e817d6eeff
             mov  eax , dword ptr [ ebp + 12 ]                               ;0x0053eb84 :        8b450c
             mov  byte ptr [ edi + eax ] , 00h                               ;0x0053eb87 :        c6040700

     Label53eb8b ::
             xor eax , eax                                                   ;0x0053eb8b :        33c0

     Label53eb8d ::
             mov  ecx , dword ptr [ ebp - 8 ]                                ;0x0053eb8d :        8b4df8
             call Fun42bf1d                                                  ;0x0053eb90 :        e888d3eeff
             pop edi                                                         ;0x0053eb95 :        5f
             pop esi                                                         ;0x0053eb96 :        5e
             pop ebx                                                         ;0x0053eb97 :        5b
             leave                                                           ;0x0053eb98 :        c9
             ret 014h                                                        ;0x0053eb99 :        c21400


4. APPLIES TO:

     VFP 6.0.8167.0
     VFP 6.0.8961.0 (SP5)

     VFP 7.0.0.9262
     VFP 7.0.0.9465 (SP1)

     VFP 8.0.0.2521
     VFP 8.0.0.3117 (SP1)

     VFP 9.0.0.2412
     VFP 9.0.0.3504 (SP1)
     VFP 9.0.0.4611 (SP2)
     VFP 9.0.0.5015 (SP2)
     VFP 9.0.0.5411 (SP2)
     VFP 9.0.0.5721 (SP2)
     VFP 9.0.0.5815 (SP2)
     VFP 9.0.0.6303 (SP2)
     VFP 9.0.0.6602 (SP2)
     VFP 9.0.0.7423 (SP2)

     The bug has been fixed in VFP Advanced.


5. REFERENCE WEBSITES:

     1, baiyujia.com:
     http://www.baiyujia.com
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix97.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix23.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix24.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix123.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix124.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix255.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix256.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix257.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix258.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix259.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix260.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix303.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix304.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix305.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix306.asp

     2, foxite.com:
     https://www.foxite.com/archives/str-rounding-problem-0000469888.htm


6. OTHER:

     For reference only, there is no guarantees.

     Any questions or suggestions, please send me an email at ccb2000@163.com.