Menu

Can't multiply by two?

Help
mkstevo
2020-03-27
2021-10-10
1 2 > >> (Page 1 of 2)
  • mkstevo

    mkstevo - 2020-03-27

    Resolved

    Well this is a new one for me. I'm working from home on a work project that requires an adjustable "success" rate.

    I'm setting a parameter which displays a pseudo percentage to the user that can be set from 10% - 90% giving the likely success. This is then used to create a large array of values which is filled with lesser or greater numbers of "success" values.

    The intention is that I end up with an array that looks like:
    1111111111111112345111111111111111 for 10%
    or:
    1123451123451123451123451123451123 for 90%

    I pass my Sub routine a parameter which has the Likelihood value passed to it, along with the maximum value (5 in the above examples). The likelihood is adjusted from 1 - 9 (displayed as 10% - 90%) . As I want high percentages to increase the chance of success, I simply deduct the Likelihood value from 10.

    To increase the steps of variation, I was trying to double the value of my likelihood variable.

    Multiplying it by 2 causes a compiler error that the variable was not declared.

    Multiplying by values other than 2 do not cause any error. As when I tried multiplying by 3 the variation seemed about right anyway, it isn't a problem but I'm confused as to why I can't multiply by 2.

    Sub ShowAnimatedScroll(In MaximumValue As Byte, In Likelihood As Byte)
    
        Dim Win_Value    As Byte
        Dim CurrValue    As Byte
        Dim JumpCount    As Byte
    
        Dim ArrayLoc     As Byte
        Dim FillValue    As Byte
        Dim WinArray(150)
    
        Dim Location     As Byte
        Let ArrayLoc = 1
        Let FillValue = StdValue
    
        For ArrayLoc = 1 to 150 Step 1
            Let WinArray(ArrayLoc) = FillValue
        Next
    
        Let JumpCount = 1
        Let FillValue = 1
    
        Let LikeliHood = 10 - LikeliHood 'Higher numbers give lower chances of winning
        Let LikeliHood = LikeliHood * 3 'this compiles
       ' Let LikeliHood = LikeliHood * 2 'this does not compile? 
    
        If GameType = RandomGame Then
            For ArrayLoc = 1 To 150 Step 1
                Let JumpCount = JumpCount + 1
                If JumpCount > LikeliHood Then
                    Let WinArray(ArrayLoc) = FillValue
                    Let FillValue = FillValue + 1
                    If FillValue > MaximumValue Then
                        Let JumpCount = 1
                        Let FillValue = 1
                    End If
                End If
            Next
        Else 'This should never happen.,..
            Let Win = FixedValueWin
            Exit Sub
        End If
    End Sub
    
     

    Last edit: Anobium 2021-10-10
  • Anobium

    Anobium - 2020-03-27

    Very hard to say without know the chip?

    And, attaching the ASM of both cases would be good.

    My guess. A total guess the method for x2 is shift register and x3 is calcualated.

     
  • mkstevo

    mkstevo - 2020-03-27

    The device is a PIC16F1829 (as ever for me!)

    Here is the section that contains the error:

    ;Let LikeliHood = 10 - LikeliHood 'Higher numbers give lower chances of winning
        banksel LIKELIHOOD
        movf    LIKELIHOOD,W
        sublw   10
        movwf   LIKELIHOOD
    ;Let LikeliHood = LikeliHood + Temp 'Add a touch of skew to make it slightly
        banksel TEMP
        movf    TEMP,W
        banksel LIKELIHOOD
        addwf   LIKELIHOOD,F
    ;less likely to win higher numbers
    ;Without this, higher maximum values are won more often.
    ;
    ;Let Likelihood = LikeliHood * 2
        bcf STATUS,C
        rlf LIKELIHOOD,F
    

    Although I don't understand Assembler, it looks as though a left rotation is being attempted?

        Let LikeliHood = 10 - LikeliHood 'Higher numbers give lower chances of winning
        Let LikeliHood = LikeliHood + Temp 'Add a touch of skew to make it slightly
                                           'less likely to win higher numbers
                                           'Without this, higher maximum values are won more often.
    '
        Let Likelihood = LikeliHood * 2
    

    Error returned:

    CS_Win_27032020.gcb (676): Error: Variable LIKELIHOOD was not explicitly declared
    
     

    Last edit: mkstevo 2020-03-27
  • Anobium

    Anobium - 2020-03-27

    Send me the source. i need to debug.

     
  • mkstevo

    mkstevo - 2020-03-27

    This is the same section of Assembler code for the multiply by three:

    ;Let LikeliHood = 10 - LikeliHood 'Higher numbers give lower chances of winning
        banksel LIKELIHOOD
        movf    LIKELIHOOD,W
        sublw   10
        movwf   LIKELIHOOD
    ;Let LikeliHood = LikeliHood + Temp 'Add a touch of skew to make it slightly
        banksel TEMP
        movf    TEMP,W
        banksel LIKELIHOOD
        addwf   LIKELIHOOD,F
    ;less likely to win higher numbers
    ;Without this, higher maximum values are won more often.
    ;
    ;Let Likelihood = LikeliHood * 3
        movf    LIKELIHOOD,W
        movwf   SysBYTETempA
        movlw   3
        movwf   SysBYTETempB
        pagesel SysMultSub
        call    SysMultSub
        pagesel $
        movf    SysBYTETempX,W
        movwf   LIKELIHOOD
    

    That does look as though it is calling a multiplication routine?

     
  • mkstevo

    mkstevo - 2020-03-27

    Sent by email, I hope that is alright? I couldn't see how to attach it to a PM.

     
  • mkstevo

    mkstevo - 2020-03-27

    Anobium kindly looked at this for me. It would appear that a bug exists where if a byte parmeter to a subroutine is attempted to be multiplied by two (no other value) the compiler erroneously flags the variable as not declared.

    The suggested work around is to cast the parameter as a word before performing the multiplication:

    #Option Explicit
    #Chip 16F1829, 32
    
      dim n1, n2, n3
    
      Subcall ( n1, n2 )
      end
    
      Sub SubCall (In MaximumValue As Byte, In Likelihood As Byte)
    
        Likelihood = Likelihood * 2 'Won't compile
        Likelihood = [word]Likelihood * 2 'Will compile
      end sub
    

    Thanks Anobium.

     
    • Anobium

      Anobium - 2021-10-10

      Resolved in the latest compiler.

      Evan

       
    • Anobium

      Anobium - 2021-10-10

      Resolved in the latest compiler.

      Evan

       
  • stan cartwright

    stan cartwright - 2020-03-27

    Instead of multiply by 2
    Try adding the value to itself... it is the same as multiplying by 2 but might be faster
    LikeliHood = LikeliHood + LikeliHood

     

    Last edit: stan cartwright 2020-03-27
    • mkstevo

      mkstevo - 2020-03-27

      I managed without the multiplication at all in the end.

      I tried adding it to itself at one point. For whatever reason, I don't think it worked as I expected. It could be that at that point I hadn't declared "LikeliHood" as In which has often caused issues with SubRoutine parameters in the past.

      Of course as a work around, adding the variable to itself should indeed have the same effect as multiplying by two.

      The initial error does still exist for the time being.

       
      • Anobium

        Anobium - 2020-03-27

        If the compiler sees 'self' added to self 'self' then the compiler will optimize to 'shift left'.
        .. which causes the same issue.
        .

         
        • stan cartwright

          stan cartwright - 2020-03-27

          I did not realise that Anobium.
          What does the compiler do with
          var=(var+var+var)-var ? ....without me trying please.
          as I don't do 328 asm

           

          Last edit: stan cartwright 2020-03-27
          • Anobium

            Anobium - 2020-03-28

            Dunno. Do try.

             
            • stan cartwright

              stan cartwright - 2020-03-29

              I did and it doesn't use shift.

              ;dim var as Byte
              ;var=20
                  movlw   20
                  movwf   VAR,ACCESS
              ;var=(var+var+var)-var
                  addwf   VAR,W,ACCESS
                  movwf   SysTemp1,ACCESS
                  movf    VAR,W,ACCESS
                  addwf   SysTemp1,W,ACCESS
                  movwf   SysTemp2,ACCESS
                  movf    VAR,W,ACCESS
                  subwf   SysTemp2,W,ACCESS
                  movwf   VAR,ACCESS
              ;End
              
               
        • mkstevo

          mkstevo - 2020-03-29

          @Anobium: If the compiler sees 'self' added to self 'self' then the compiler will optimize to 'shift left'... Which causes the same issue.

          Thanks for the explanation. I thought I'd tried it...

           

          Last edit: mkstevo 2020-03-29
          • Anobium

            Anobium - 2020-03-29

            Yep. :-(

             
  • stan cartwright

    stan cartwright - 2020-03-27

    Where is Dim LikeliHood and as what ?
    Why dim vars in a sub, why not at the start of your code?
    Are you using #option explicit ?
    Just thinking.

     
    • mkstevo

      mkstevo - 2020-03-29

      @stanleyella: Where is Dim LikeliHood?

      Here:

      'Great Cow Basic
        Sub SubCall (In MaximumValue As Byte, In Likelihood As Byte)
      

      @stanleyella: Why dim vars in a sub, why not at the start of your code?

      I spent a lot of time programming in Delphi where procedures and functions were mandatory. A similar procedure in Object Pascal would look like:

      //Pseudo Pascal - It has been well over ten years since I wrote in Pascal, and I am sure this is not remotely Delphi compatible
      
      // Declare the procedure and required parameters
      Type
          TMyProgamName = Class(TProgram)
          Procedure SubCall(MaximumValue, Likelihood: Integer);
      end; //Type declaration ends
      
      var;
          MyGlobalVar: Integer;
      
      implementation
      
      Begin
          Procedure TMyProgramName.SubCall(MaximumValue, Likelihood: Integer);
          Var
              n1, n2, n3: Integer;
      
          Begin
              n1 := MaximumValue;
              n2 := LikeliHood;
              n3 := LikeliHood * 2;
              LikeliHood := n2 +((LikeliHood * 2) + MaximumValue));
              If MaximumValue = 4 Then
              Begin
                  n3 := likeliHood;
                  MyGlobalVar := MyGlobalVar + 1;
              End; //If ends
          End; //Procedure ends
      End; //Program ends
      

      In this case the variables n1, n2 and n3 would only be visible within the SubCall procedure. Any subsequent procedures would have to re-declare them before they could be used, the advantage is that you could do anything to those values and it wouldn't affect values in other procedures. The parameters passed would be mandatory in any calls to the procedure, and crucially, as the procedure was declared in the "Type" declaration, any calls to the procedure must have the parameter values as integer values, or integer variables. Attempting to call it with a LongInt value or LongInt variable (or other type of variable that wasn't explicitly of the Type Integer) would result in a compilation error with a 'Type Mismatch error'. This could catch errors where Byte and Word values/variables were mixed and could potentially overflow. MyGlobalVar would have it's value changed and that value (and that variable) would be visible to any subsequent procedures.

      in GCB there is less advantage to declaring variables within subroutines using the 'Dim MyVariable As Byte' declaration as (so far as I understand) all variables declared using Dim are automatically Global in scope. But old habits die hard, and I do from time to time find myself declaring (pointlessly) them in this way.

      Parameters passed to a subroutine in GCB are often passed only as an alias, where if a variable value is used in the call to the subroutine [ SubCall(AVariable, AnotherVariable) ] any changes to MaximumValue or LikeliHood directly affect the values of variables AVariable and AnotherVariable everywhere they might be used subsequently. This is why I have used an "In" declaration. The variables AVariable and AnotherVariable will now be unaffected by any maths within the SubCall subroutine.

      If I could wave a magic wand, I'd love to see local variable scope in GCB. It would suit my methodolgy superbly. Due to the nature of the PIC device and the PIC assembler language, I'm not sure it is actually possible even with that magic wand.

       

      Last edit: mkstevo 2020-03-29
      • Anobium

        Anobium - 2020-03-29

        Magic wand request has been on the list a while. :-)

         
        • mkstevo

          mkstevo - 2020-03-30

          @evanvennn :Magic wand request has been on the list a while. :-)

          Ooh... Now I'm excited!

           
      • stan cartwright

        stan cartwright - 2020-03-29

        I only learnt interpreted simple basic in 1981. Gosub was simpler then.

         
  • jackjames

    jackjames - 2020-03-29

    In another commercial BASIC compiler, the variables declared inside a routine, even if they have the same name as other externals, are renamed with the suffix given by the name of the routine plus "_" plus the name of the variable.
    In this way they remain confined within the routine.

     
    • Anobium

      Anobium - 2020-03-29

      Yes, Noted.

       
    • mkstevo

      mkstevo - 2020-03-30

      @JackJames :In another commercial BASIC compiler, the variables declared inside a routine, even if they have the same name as other externals, are renamed with the suffix given by the name of the routine plus "_" plus the name of the variable.
      In this way they remain confined within the routine.

      That does sound like one way of doing things.

      Would that not be 'wasteful' of RAM though? I have not had problems with RAM on the devices I tend to use, but I can see that it might become problematic with some of the low end devices. An ideal case would be that the local variables were destroyed after leaving their local scope, though as I said earlier, I'm not sure that could be done on a PIC.

       

      Last edit: mkstevo 2020-03-30
1 2 > >> (Page 1 of 2)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.