News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

FloatToStr and FloatToStr2

Started by Bokepatza, June 28, 2009, 05:00:26 PM

Previous topic - Next topic

Bokepatza

Hi all again,

I'm now using FloatToStr and FloatToStr2 to convert REAL8 to string.

I have written this code


        paso    EQU  0.01

        mov     iter,25
        push    edi
        xor     edi,edi
        .WHILE  (iter)
                fld     valor
                fadd    paso
                fstp     valor
                invoke  FloatToStr2,valor,addr buffer
                print   addr buffer
                newline
                dec     iter
        .ENDW
        pop     edi
        getkey


and the result is this
Quote
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1
0.1099999999999999
0.1199999999999999
0.1299999999999999
0.1399999999999999
0.15
0.16
0.17
0.18
0.19
0.2
0.21
0.22
0.23
0.24
What's wrong with that? Why a 0.11 value is shown as 0.1099999999999999?

Is there any other routine, besides FloatToStr and FloatToStr2, which can be used to convert REAL8 to string?

I'm looking for any in which I can specify how many decimal numbers to show and if I want Scientific notation or not

Thanks for your atention

jj2007

Float$ should do the job.

.nolist
include \masm32\include\masm32rt.inc
include \masm32\include\Float2Asc.inc

.data
iter dd 0
valor REAL8 0.0
paso REAL8 0.0100000000001 ; we cheat a little bit

.code
start:

print "Testing float$", 13, 10
mov iter, 25
fld paso
fld valor
.WHILE iter
fadd ST, ST(1)
fst valor
print float$("\nValue=%2f", valor)
dec iter
.ENDW
getkey
exit

end start


CONSOLE assembly ;-)

Bokepatza

Thanks for your fast answer jj2007

I now have Float2Asc.inc and code as follows


        mov     iter,25
        push    edi
        xor     edi,edi
        .WHILE  (iter)
                fld     Bessel_Tabla[edi].x
                fstp    valor
                print float$("\n%2f", valor)
                add     edi,16
                dec     iter
        .ENDW
        pop     edi
        getkey


And the result is this:
Quote
0
0.010
0.020
0.030
0.040
0.050
0.060
0.070
0.080
0.090
0.1.00
0.11
0.12
.
.
.

Why I have 3 decimals in the first ones and 2 decimals in the last?
And what happens with 0.1.00 ?  ::)


Refering to the declaration of "paso", it's a value I calculated like this

        fld     lim_sup
        fsub    lim_inf
        fidiv   num_valores
        fstp    paso


Should I make fadd 0.0000000000001 after fidiv?


Thanks again for your atention


Bokepatza

Quote from: dedndave on June 28, 2009, 06:24:04 PM
http://www.masm32.com/board/index.php?action=dlattach;topic=9756.0;id=6041

Thanks dedndave

I now have Float2Asc.inc, but have the problem I posted above.

I will need the REAL8 value in a string in order to store it in another string or in a Control List View, so I think I can't try this way. Is there another routine which converts REAL8 to a string?

And what about 0.1.00 value I got?

dedndave

i used to have tricks for this - i am trying to remember what they were - lol
some kind of a "fix()" function to set the number of decimal places
give me a little time - it will come to me
of course, you could add a small fraction to any and all results, then select the number of digits with a string function

for example,

0.1099999999999999 + 0.0000000000000002 = 0.1100000000000001
0.1100000000000000 + 0.0000000000000002 = 0.1100000000000002

take the result and use something like the left$ function to extract the ascii digits you want
(or just terminate the string with an ascii 0 at the appropriate place)

EDIT
actually, adding 0.0000000000000001 should do the trick

EDIT
a better approach might be to multiply everything by 1.00000000000001 (carefully notice the number of 0's)
that way, it scales itself according to the magnitude of the original value
you may be able to work this constant into the original equation so as not to use an additional step

jj2007

Quote from: Bokepatza on June 28, 2009, 06:02:17 PM
Why I have 3 decimals in the first ones and 2 decimals in the last?

float$ has a variable number of precision digits:
Quoteprint STR$("\nValue=%2f", valor)

Quote
And what happens with 0.1.00 ?  ::)

That is clearly a bug that I have to investigate, but there is a workaround:

paso   REAL8 0.0100000000000001   ; we cheat a little bit

Full code see above.

dedndave

oh - i think Jochen and i are speaking the same language - lol

jj2007

Yes but this bug is clearly annoying. I have to investigate...

In the meantime, there is...

print real8$(valor)

... from the Masm32 library, a wrapper around a C function. Slow but might just work fine.

For both options:
Find the dot, then just move some chars right and use mov byte ptr [edx+ecx+n], 0

mov edx, float$("\nValue=%2f", valor)
xor ecx, ecx
.Repeat
inc ecx
mov al, [edx+ecx]
.Until al=="."
mov byte ptr [edx+ecx+3], 0
print edx


Output:
Value=0.01
Value=0.02
Value=0.03
Value=0.04
Value=0.05
Value=0.06
Value=0.07
Value=0.08
Value=0.09
Value=0.10
Value=0.11
Value=0.12
Value=0.13
Value=0.14
Value=0.15
Value=0.16
Value=0.17
Value=0.18
Value=0.19
Value=0.20
Value=0.21
Value=0.22
Value=0.23
Value=0.24
Value=0.25

MichaelW

Just use the CRT. And keep in mind that the vast majority of real numbers cannot be represented exactly in the floating-point format, so most floating-point results are just very close approximations.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      value     REAL8 0.0
      increment REAL8 0.01
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    mov ebx, 24
    .WHILE ebx
      fld value
      fld increment
      fadd
      fstsw ax              ; get FPU status word into AX
      fstp value
      fwait                 ; make sure that fstsw has completed
      test ax, 1 SHL 5      ; test bit 5 for precision exception
      jnz inexact
      invoke crt_printf,chr$("%.2f",9,"%.2e",9," ",10),value,value
      jmp @F
    inexact:
      invoke crt_printf,chr$("%.2f",9,"%.2e",9,"inexact",10),value,value
    @@:
      dec ebx
    .ENDW

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


0.01    1.00e-002
0.02    2.00e-002
0.03    3.00e-002       inexact
0.04    4.00e-002       inexact
0.05    5.00e-002       inexact
0.06    6.00e-002       inexact
0.07    7.00e-002       inexact
0.08    8.00e-002       inexact
0.09    9.00e-002       inexact
0.10    1.00e-001       inexact
0.11    1.10e-001       inexact
0.12    1.20e-001       inexact
0.13    1.30e-001       inexact
0.14    1.40e-001       inexact
0.15    1.50e-001       inexact
0.16    1.60e-001       inexact
0.17    1.70e-001       inexact
0.18    1.80e-001       inexact
0.19    1.90e-001       inexact
0.20    2.00e-001       inexact
0.21    2.10e-001       inexact
0.22    2.20e-001       inexact
0.23    2.30e-001       inexact
0.24    2.40e-001       inexact

eschew obfuscation

raymond

Bokepatza
You may also want to consider the FpuFLtoA function from the Fpulib provided with the MASM32 package. However, it is designed to be used with REAL10 floats and you would have to load your REAL8 data onto the FPU yourself and use the function as follows if your float is in memory. If your float is already on the FPU, there is no need to store it and reload it again regardless if you consider it as a REAL8 or a REAL4.

fld  real8_var    ;load from memory
invoke FpuFLtoA,0,xxx,ADDR buffer, SRC1_FPU or SRC2_DIMM
fstp st     ;only if you don't need to reuse it


That function has an additional feature over the other ones which have been mentioned. The low byte of the "xxx" dword argument specifies the number of decimal places required in the string. In addition, the second byte can be used to specify the offset of the decimal point by padding the front end of the string with spaces if you ever need such alignment when you display several strings one under the other which may have a variable number of integer digits.

Read the Fpulib help file for more info about that function.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

ToutEnMasm


For example,you can also link to the libcmt.lib (vc++ 2008 express)
There is just to add this declare:
Quote
extern c _FPinit:dword   ; to load floating point library
Then used the strsafe .inc and .lib , that you can find in this forum or in the sdk.
And now let's go:                  StringCbPrintfEx
You can print float with the number of decimal you want, decimal number,exponentiel,hexadecimal ....
you can also add some .sdk files
Quote
               include windows.inc
              ...............
   include     \sdkrc7\translate.inc
   include     float.sdk

and now can filter the NAN and infinite numbers and manythings more.....






Bokepatza

#12
Thank you a lot, everyone. You all help me too much. :U
I test almost all suggestions and run for me. :clap:

I programmed so easy applications years ago in ASM and now MASM is completely new for me.

Now I can print REAL on screen or save it in a string.

All I have to do is calculate values from a function with the fpu, which I have already done, and then show them on a window, which can be the console, or any other. Then, the program should allow to scroll the table of values with arrow keys, PgDown, PgUp, Home and End.

I took a look to Iczelion's Manual http://win32assembly.online.fr/tutorials.html and see the common control listview and take as a possibility to do what I need. I can define several columns and a row per value, that's why I need to convert REAL to string.

As I'm completely noob, anyone support my choice of a control listview? Or it will be easier or better by other way?

I'll be shoulders to the wheel with the control list view

Thank you all again  :wink