News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

multiplying/dividing a positive decimal number by a positive number

Started by shankle, February 28, 2015, 01:57:08 PM

Previous topic - Next topic

shankle

Let's say the results from the FPU calculations should be 500.
The actual amount is 500.40.
I have not modified the Control Word Rc field.
The code I wrote seems to be basically working.
I am thinking the code is rounding up. 

dedndave

the default is 00, round to nearest
for most applications, that's the right one to use

you are comparing some FPU result to some calculator result, i guess
i'd tend to believe the FPU over most calculators - lol

but - you were talking about limiting the number of digits
setting the FPU to truncate is not the same as truncating the string

QuoteLet's say the results from the FPU calculations should be 500.
The actual amount is 500.40.

not sure when you say "should be"

dedndave

let's use your previous example:

1.00416 / 15

0.06694399999999999

what do you want to see as a result ?

dedndave

changing the rounding bits may have undesirable effects for intermediate calculations
that's why i say it's usually best to use "round to nearest"

then, massage the resulting string to suit your needs

shankle

In a previous post I limited the resolution to 5 decimal places.
So in answer to Dave it would be .00694.

Since I have not modified the Control Word, I assume it's set to the default.

dedndave

0.06694399999999999
      ^


i would go one digit past the carot above, that would be a "3"
because that digit is less than "5", simply truncate to the "4" by placing a null where the "3" is
if that digit were "5" or higher, i would truncate the same way, but add one to the remaining string
notice that, when you add one, you have to ripple carry   :P
in some cases, ripple carry might cause the string to lengthen - lol

a better solution might be to have a floating point conversion routine that sets the number of returned digits

shankle

PROBLEM SOLVED! - (I Think)
Using the longer decimal resolutions fixed the problem.
I think I will be a FPU Expert in about another 99.9999 years :biggrin: :biggrin: :biggrin:
Thanks guys

dedndave

it just occured to me that the MSVCRT probably has a function to do this
i don't use it much but let me look around a bit

dedndave

looks like printf can do what you like

MSDN reads like stereo instructions
but, here's a tutorial that might be easier to understand...

http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output

dedndave

here's a quick go at it
this works for console mode
for gui mode, you might have to create a buffer and use fprintf or sprintf (i don't know which)

as it happens, crt_printf wants to see a double (REAL8)

;###############################################################################################

        .XCREF
        .NoList
        INCLUDE    \Masm32\Include\Masm32rt.inc
        .List

;###############################################################################################

        .DATA

n1  REAL8 1.00416
n2  REAL8 15.0

szFloatFormat db "%7.5f",0

;***********************************************************************************************

        .DATA?

n3  REAL8 ?

;###############################################################################################

        .CODE

;***********************************************************************************************

main    PROC

    fld     n1   ; Load n1 into the ST0 register on the FPU stack.
    fdiv    n2   ; Divide it by n2 directly from memory.
    fstp    n3   ; Pop the result off the stack to memory

    INVOKE  crt_printf,offset szFloatFormat,n3

    print   chr$(13,10)

    inkey
    exit

main    ENDP

;###############################################################################################

        END     main


szFloatFormat db "%7.5f",0
at least 7 wide, with precision of 5

result
0.06694
Press any key to continue ...


shankle

        3-16-2015
Thanks for any help.

n1         dq  0
buf        db '              ',0
HoldValue  dd  '0010000.00   ',0

This code does not work
The decimal places are not showing up in the TextOut instruction.
The documentation is confusing and I can't tell which atodbl addresses
decimal points
The value from n1 shows in TextOut as 0010000.

invoke msvcrt:_atodbl, addr n1,addr HoldValue ;convert string to double
invoke msvcrt:sprintf_s, addr buf,sizeof buf,\
                "%g",[n1]
invoke TextOut, [hdc],200,345,addr buf,13


dedndave

HoldValue  dd  '0010000.00   ',0

did you mean "DD" or "DB" ?

anyways....
if the fraction part is 0, it won't appear
that's pretty normal float-to-string behaviour


shankle

        3-18-2015
Thanks for any help.

n1         dq  0
Value      dq  19.31
buf        db '              ',0
HoldValue  db '0010000.00   ',0

This code does not work
The decimal places are not showing up in the TextOut instruction.
The Microsofts documentation is confusing and I can't tell which _atodbl
to use. Maybe I am using the wrong one.

    invoke msvcrt:_atodbl, addr n1,addr HoldValue ;convert string to double
    fld Q[n1]   ; load n1 into the ST0 register on the fpu stack
    fsub Q[Value] ; subtract Value from amount in ST0
    fstp Q[n1] ; pop the results off the stack to memory
    invoke msvcrt:sprintf_s,addr buf,sizeof buf,\
                   "%g",[n1]
    invoke TextOut, [hdc],200,345,addr buf,13

The result is 9981 - instead of 9980.69

dedndave