Calc Macro Bug - "If" evaluates to false when it should evaluate true

Version: 24.2.4.2 (X86_64) / LibreOffice Community
Build ID: 420(Build:2)
CPU threads: 16; OS: Linux 6.6; UI render: default; VCL: gtk3
Locale: en-NZ (en_NZ.UTF-8); UI: en-US
24.2.4-1
Calc: threaded

I’ve created a basic macro function within LibreOffice Calc. It’s a simple function so far, one that I am currently building to calculate a mathematical division table for base 12 mathematics.

It’s mostly working except during testing I’ve noted a weird bug that I can’t explain and that makes no sense to me. For basic testing I tried 1/1, 2/2, 3/3, 4/4, 5/5, 6/6, 7/7, 8,8, 9/9, 10/10, 11/11 and 12/12 by passing these two respective values as parameters into this macro function. They should all return 1 as the result and all do except 11/11 which just wants to be different for some reason and returns .XZ instead, which is a fractional value with the last two characters I am using for base 12.

The basic macro is as follows;

Public Function B12_Divide( DivBase as Integer, DivFactor as Integer) as String
	Dim AngleFactor             As Double
	Dim BaseCharacters      As String
	Dim BaseFactor               As Integer
	Dim BaseAngle                As Double
	Dim CurrentAngle          As Double
	Dim CurrentSegment   As Integer
	Dim CurrentSequence  As Integer
	Dim DivAngle                   As Double
	'Dim DivBase                    As Integer
'	Dim DivFactor                 As Integer
	Dim DivRatio                   As Double
	Dim RefAngle                  As Double
	Dim ResultCharacters  As String
	Dim ResultPrecision     As Integer
	Dim ZeroBased               As Boolean
	
	AngleFactor            = 360
    BaseCharacters     = "-.0123456789XYZ"
	BaseFactor              = 12
	BaseAngle               = AngleFactor / BaseFactor
	CurrentAngle         = 0
	CurrentSegment  = 0
	CurrentSequence = 0
	'DivBase                    = 12
	'DivFactor                 = 7
	DivRatio                   =  (( BaseAngle / DivFactor ) * DivBase ) / BaseAngle
	DivAngle                  =  DivRatio * BaseAngle
	RefAngle                  = BaseAngle
	ResultCharacters  = ""
	ResultPrecision      = 6
	ZeroBased               = False ' TODO: TEST = True
	
	If DivRatio < 1 Then
		If ZeroBased Then ResultCharacters = ResultCharacters + Mid(BaseCharacters, 3, 1)
		ResultCharacters = ResultCharacters + "."
	End If
    	
	ReSequence:
		CurrentSequence = CurrentSequence + 1	
		If CurrentSequence = ResultPrecision  + 2 Then Goto Result
		
		CurrentSegment  = 0
	ReSegment:
		If (CurrentAngle + RefAngle) <= DivAngle Then
			CurrentSegment = CurrentSegment + 1
			       CurrentAngle= CurrentAngle + RefAngle
			       
			Goto ReSegment
		Else						
			If ZeroBased Then ResultCharacters = ResultCharacters + Mid(BaseCharacters, CurrentSegment + 3, 1) _
			Else If CurrentSegment > 0 Then ResultCharacters = ResultCharacters + Mid(BaseCharacters, CurrentSegment + 3, 1)
			
			If Len(ResultCharacters) = 1 And (DivRatio >= 1) Then ResultCharacters = ResultCharacters + Mid(BaseCharacters, 2, 1)
			
			RefAngle = RefAngle / BaseFactor							
			Goto ReSequence
		End If
		
	Result:
		If Right(ResultCharacters, 1) =  Mid(BaseCharacters, 2, 1) Then ResultCharacters = Left(ResultCharacters, Len(ResultCharacters) - 1)
		B12_Divide = ResultCharacters
End Function

For 11/11, it appears to be failing at the line;

“If (CurrentAngle + RefAngle) <= DivAngle Then”

They all reach this line with CurrentAngle = 0, RefAngle=30 and DivAngle=30, but unlike all the other division tests, this equality test fails here for 11/11 and falls into the else block. I cant really make any sense of it as using watch values to follow it and track it, it pretty much evaluates

“If (0 + 30) <= 30 Then”

as false which makes no logical sense.

This macro is also compatible with Microsoft Excel. When I import this into Excel and test it there it works perfectly for all those tests, but for some reason LibreOffice Calc falls over with the 11/11 division parameters even though I don’t see how that has any bearing on the if evaluation.

Can anybody out there reproduce this bug on their end and if so have any idea why this is happening?

Welcome to the forum and to the world of approximate computing. :slightly_smiling_face:

Let’s add the following line before the ReSequence: label:

 Msgbox CurrentAngle + RefAngle - DivAngle	

I see: 3,5527136788005E-015

Huh. Yeah, I get that exact message as well with the MsgBox as you suggested when calling B12_Divide(11,11).

There must be some precision error occuring behind the scenes for some reason that only presents itself with 11 as the parameters.

We must take these features into account (and in Excel) and write something like this:

If (CurrentAngle + RefAngle) <= DivAngle  + 1E-14 Then

Instead of 1E-14, there may be another small number (taking into account possible rounding errors), depending on the specifics of the task.

Yep, your suggestion fixed the issue.

I did though also have to add it to;

If DivRatio < 1 - 1E-14 Then

;as well, as that code tries to add a “.” character prefix to the result when DivRatio is supposed to be less then 1 but seemed to have got confused here as well. It now outputs 1 correctly and doesn’t seem to have affected the other division factors.

Thanks sokol92, I really appreciate your help here. I guess I had this coming with a function with nested divisions. I will keep this in mind from now on.

Cheers.

1 Like