Proc works for Addition, subtraction, multiplication, not division???

Started by devilhorse, October 15, 2010, 06:12:27 PM

Previous topic - Next topic

devilhorse

I am writing a math tutoring program. The user can select either an addition, subtraction, multiplication or division set of problems. The user clicks a button and the computer generates the math problem and stores the answer in a dword variable The user types his or her answer into an edit box. When the "enter" key is pressed a procedure named "CheckAnswer". The problem is when I check the answer for the division problem it always says "Wrong" on the appropriate static control. The Addition, Multiplication, and Subtraction work correctly when checked. Do I need to change the comparison portion of the CheckAnswer code? or do I need to change the DoTheDivision procedure. I have posted the relevant code. Any hints are much appreciated.


CheckAnswer Proc
Local value1:DWord
.If timeLeft > 0

Invoke GetText,heditUserAnswer,Addr value1;<-Stores the answer the user typed into hedituserAnswer edit control
   Invoke lstrcmp, Addr value1,Addr result ;<-This is a global dword to hold the computer-generated answer
   .If Eax == 0
      Invoke KillTimer,App.Main,1 ; Make sure the timer doesn't restart by destroying it
      Invoke SetText, hStatNotify,CTXT("Correct")
      Invoke SetFocus,hNextQuestionButton
      Invoke SendDlgItemMessage,App.Main,IDC_WINDOW1_NEXTQUESTION, WM_ENABLE, TRUE, 0
         .Else
            Invoke SetText, hStatNotify,CTXT("Wrong")
               Invoke SetText, heditUserAnswer,NULL
      .EndIf
.EndIf

   Ret
CheckAnswer EndP


DoTheAddition Proc
   
   LOCAL var1:DWORD
   Local value1:DWord
   Local value2:DWord

   Invoke Value,Addr NumeralOneSzLeftAsciiBuffer
   Mov value1,Eax

   Invoke Value,Addr NumeralTwoSzLeftAsciiBuffer
   Mov value2,Eax

    Fild value1   ; load addend
    Fild value2   ; load addend
    Fadd          ; do the addition
    Fistp var1    ; store result in variable
   
    Invoke dwtoa,var1,Addr result
   
   Ret
DoTheAddition EndP

;==============================================

DoTheSubtraction Proc
   Local var1:DWord
   Local value1:DWord
   Local value2:DWord

   Invoke Value,Addr NumeralOneSzLeftAsciiBuffer
   Mov value1,Eax

   Invoke Value,Addr NumeralTwoSzLeftAsciiBuffer
   Mov value2,Eax

    Fild value1   ;
    Fild value2   ;
    Fsub            ;
    Fistp var1      ; store result in variable
   
    Invoke dwtoa,var1,Addr result
   Ret
DoTheSubtraction EndP

;=================================================

DoTheMultiplication Proc

   LOCAL var1:DWORD
   Local value1:DWord
   Local value2:DWord

   Invoke Value,Addr NumeralOneSzLeftAsciiBuffer
   Mov value1,Eax

   Invoke Value,Addr NumeralTwoSzLeftAsciiBuffer
   Mov value2,Eax

    Fild value1      ; load multiplicand
    Fild value2      ; load multiplier
    Fmul             ; do multiplication
    Fistp var1      ; store result in variable
   
    Invoke dwtoa,var1, Addr result
       Ret
DoTheMultiplication EndP

DoTheDivision Proc
   
   Local var1:DWord
   ;Local value1:DWord
   Local ascBuf[24]:Byte
   Local floatValue1:Real10
   Local floatValue2:Real10

Invoke lstrcat, Addr NumeralOneSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
Invoke FpuAtoFL,Addr NumeralOneSzLeftAsciiBuffer,Addr floatValue1,DEST_MEM

Invoke lstrcat, Addr NumeralTwoSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
Invoke FpuAtoFL,Addr NumeralTwoSzLeftAsciiBuffer,Addr floatValue2,DEST_MEM

   Finit
    Fld floatValue1
    Fld floatValue2
    Fdiv
    Fst  var1

   Invoke FpuFLtoA, Addr var1, 2, Addr result, SRC1_FPU Or SRC2_DIMM

   Ret
DoTheDivision EndP

;=============================================

clive

QuoteDoTheDivision Proc
   
   Local var1:DWord
   ;Local value1:DWord
   Local ascBuf[24]:Byte
   Local floatValue1:Real10
   Local floatValue2:Real10

Invoke lstrcat, Addr NumeralOneSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
Invoke FpuAtoFL,Addr NumeralOneSzLeftAsciiBuffer,Addr floatValue1,DEST_MEM

Invoke lstrcat, Addr NumeralTwoSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
Invoke FpuAtoFL,Addr NumeralTwoSzLeftAsciiBuffer,Addr floatValue2,DEST_MEM

   Finit
    Fld floatValue1
    Fld floatValue2
    Fdiv
    Fst  var1

   Invoke FpuFLtoA, Addr var1, 2, Addr result, SRC1_FPU Or SRC2_DIMM

   Ret
DoTheDivision EndP

You still have var1 defined as a DWORD, presumably you want it as a REAL10?
Why don't you display or look at the data in result before you do the comparison to check if it is what you expect?
It could be a random act of randomness. Those happen a lot as well.

devilhorse

Even if I define var1 as Real4 the outcome is the same. I added two messageboxes; one to view the computer-generated answer, and the other two show the user input answer. Even if the answers are exactly the same in both message boxes, the procedure CheckAnswer says the answer is "wrong". I thought by putting the values into byte buffers I would effectively be able to compare the buffers using lstrcmp or szCmp. It is still not working for the division.

clive

It could be a random act of randomness. Those happen a lot as well.


clive

Ok, debugging with a simple port to MASM

        .nolist
        include \masm32\include\masm32rt.inc
        include \masm32\fpulib\fpu.inc
        includelib \masm32\fpulib\fpu.lib
        .list

        .DATA

result  db      24 dup (?)
NumeralOneSzLeftAsciiBuffer db  "12", 0, 8 dup (?)
NumeralTwoSzLeftAsciiBuffer db  "4", 0, 8 dup (?)

        .CODE

_start:
        call    DoTheDivision
        ret

DoTheDivision Proc

   Local var1:Real10
   Local floatValue1:Real10
   Local floatValue2:Real10

        Invoke lstrcat, Addr NumeralOneSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
        Invoke FpuAtoFL,Addr NumeralOneSzLeftAsciiBuffer,Addr floatValue1,DEST_MEM

        Invoke lstrcat, Addr NumeralTwoSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
        Invoke FpuAtoFL,Addr NumeralTwoSzLeftAsciiBuffer,Addr floatValue2,DEST_MEM

    Finit
    Fld floatValue1
    Fld floatValue2
    Fdiv
    Fstp  var1

   Invoke FpuFLtoA, Addr var1, 2, Addr result, SRC1_REAL Or SRC2_DIMM

        print addr result, 13, 10

   Ret
DoTheDivision EndP

        END     _start


Observations:
Your parameters on FpuFLtoA were wrong.
I'd pop the value from the FPU stack.
The output has a leading space. So 12 / 4 reports " 3.00"
Better make sure to handle the space, and the decimal places in your comparison.
It could be a random act of randomness. Those happen a lot as well.

devilhorse

I took your advice and I used szLtrim to remove the leading space from the output from FpuAtoFl.  The procedure works correct now. I still need to code to handle the ".00" that may appear at the end of some answers. I know how to do that. I must tell you that changing the var1 to a Real10 produced an error. So I kept as a dword. Thanks for your help. You provided the direction I needed without doing the work for me. That is how a forum should work, in my opinion, to give direction to people who want to LEARN how to do something with maybe a little guidance here and there. Again. Thank you so much!

DoTheDivision Proc
   Local tmpBuffer[24]:Byte
   Local var1:DWord
   Local floatValue1:Real10
   Local floatValue2:Real10

Invoke lstrcat, Addr NumeralOneSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
Invoke FpuAtoFL,Addr NumeralOneSzLeftAsciiBuffer,Addr floatValue1,DEST_MEM

Invoke lstrcat, Addr NumeralTwoSzLeftAsciiBuffer,CTXT(".0") ;add .0 for use in FPU
Invoke FpuAtoFL,Addr NumeralTwoSzLeftAsciiBuffer,Addr floatValue2,DEST_MEM

   Finit
    Fld floatValue1
    Fld floatValue2
    Fdiv
    Fst  var1

   Invoke FpuFLtoA, Addr var1, 2, Addr tmpBuffer, SRC1_FPU Or SRC2_DIMM
   Invoke szLtrim,Addr tmpBuffer,Addr result
   Ret
DoTheDivision EndP