# Problem Storing Arrays Inside Arrays

## Recommended Posts

Hello guys, I have a matrix inverse function that I am trying to improve the accuracy of by making it preform math on fractions instead of floats, however is appears I'm having issues accessing an array embedded inside a 2D array (\$array[1][1][0]) where [0] would contain a 1D array with 2 values in it.

See my code below, and as always thanks a ton! (you will need the fractions UDF '?do=embed' frameborder='0' data-embedContent>>)

```#include "fractions.au3"
#include <array.au3>

_inv_big(\$matricies[0])

Func _inv_big(\$m)
Local \$n = UBound(\$m, 1)
Local \$a[\$n][2 * \$n]
Local \$inv[\$n][\$n]
Local \$temprow[2 * \$n]
Local \$pivelt, \$tarelt, \$pivrow, \$tarrow, \$k, \$i, \$j
#Region - Filling matrix A
For \$i = 0 To \$n - 1
For \$j = 0 To \$n - 1
\$a[\$i][\$j] = \$m[\$i][\$j]
Next
Next
For \$i = 0 To \$n - 1
\$a[\$i][\$n + \$i] = 1
Next
#EndRegion - Filling matrix A
#Region - Inverting matrix \$M
For \$pivrow = 0 To \$n - 1
\$pivelt = \$a[\$pivrow][\$pivrow]
If (\$pivelt == 0) Then
\$k = \$pivrow + 1
While (\$pivelt == 0 AND \$k <= \$n)
\$pivelt = \$a[\$k][\$pivrow]
\$k = \$k + 1
WEnd
If (\$pivelt == 0) Then
SetError(1)
Return
Else
For \$i = 0 To 2 * \$n - 1
\$temprow[\$pivrow][\$i] = \$a[\$pivrow][\$i]
\$k = \$k - 1
Next
For \$i = 0 To 2 * \$n - 1
\$a[\$pivrow][\$i] = \$a[\$k][\$i]
Next
For \$i = 0 To 2 * \$n - 1
\$a[\$k][\$i] = \$temprow[\$k][\$i]
Next
EndIf
EndIf
For \$i = 0 To 2 * \$n - 1
\$a[\$pivrow][\$i] = _fraction(Number(\$a[\$pivrow][\$i]), Number(\$pivelt))
;array is accessable here
Next
#Region - replace all other rows by target
For \$tarrow = 0 To \$n - 1
If (\$tarrow <> \$pivrow) Then
\$tarelt = \$a[\$tarrow][\$pivrow]
For \$i = 0 To 2 * \$n - 1
\$a[\$tarrow][\$i] = _FractionSubtract(_fraction(number(\$a[\$tarrow][\$i])), _FractionMultiply(\$a[\$pivrow][\$i], _fraction(number(\$tarelt))))
_ArrayDisplay(\$a[\$tarrow][\$i])
;array is accessable here via _arraydisplay() but when I try to consolewrite the values it says the dimension range is exceeded
ConsoleWrite(\$a[\$tarrow][\$i][0]&'/'&\$a[\$tarrow][\$i][1]&@CRLF)

Next
EndIf
Next
;array is accessable here with _arraydisplay but still not via any other method
#EndRegion - Now replace all other rows by target row minus pivot row times element in target row and pivot colum
Next
_ArrayDisplay(\$a)
;array is nullified, all values for the array get set to 1
#Region - finally extract the inverse from columns N+1 to 2N
For \$i = 0 To \$n - 1
For \$j = 0 To \$n - 1
\$inv[\$i][\$j] = \$a[\$i][\$n + \$j]
Next
Next
#EndRegion - finally extract the inverse from columns N+1 to 2N
Return \$inv
#EndRegion - Inverting matrix \$M
EndFunc

Func _datagen()
Local \$ret
For \$i = 1 To 112
Local \$data = ""
For \$x = 0 To 7
For \$y = 0 To 7
\$data &= Random(111111111, 99999999999, 1) & ","
Next
\$data = StringTrimRight(\$data, 1) & "/"
Next
\$ret &= StringTrimRight(\$data, 1) & "|"
Next
Return \$ret
EndFunc

Local \$dataz[\$z]
\$array = StringSplit(\$data, "|")
If \$array[0] < \$z - 1 Then Return 0
For \$i = 0 To \$z - 1
\$dataz[\$i] = _stringtoarray(\$data, \$i)
If \$dataz[\$i] = 0 Then
Return 0
EndIf
Next
Return \$dataz
EndFunc

Func _stringtoarray(\$data, \$n = 0)
\$array = StringSplit(\$data, "|", 2)
\$next = StringSplit(\$array[\$n], "/")
\$num2 = StringSplit(\$next[1], ",")
Local \$ar1[\$next[0]][\$num2[0]]
For \$i2 = 1 To \$next[0]
\$next2 = StringSplit(\$next[\$i2], ",", 2)
For \$i3 = 0 To UBound(\$next2) - 1
If \$i2 - 1 > \$next[0] - 1 OR \$i3 > \$num2[0] - 1 OR \$i3 > UBound(\$next2) Then
Return 0
EndIf
\$ar1[\$i2 - 1][\$i3] = \$next2[\$i3]
Next
Next
Return \$ar1
EndFunc```

##### Share on other sites

\$array[1][1][0]  is for a 3D array

Try this :  (\$array[1][1])[0]

Edit

I mean

`ConsoleWrite((\$a[\$tarrow][\$i])[0]&'/'&(\$a[\$tarrow][\$i])[1]&@CRLF)`
Edited by mikell

##### Share on other sites

Yes using a 3D array is simpler than my suggestion here:

Either way is good, and mikell's way is also good, if you do decide to store arrays inside another. So much choice! I woulld use a 3D array: new example posted in the link.

Edited by czardas

##### Share on other sites

\$array[1][1][0]  is for a 3D array

Try this :  (\$array[1][1])[0]

Edit

I mean

`ConsoleWrite((\$a[\$tarrow][\$i])[0]&'/'&(\$a[\$tarrow][\$i])[1]&@CRLF)`

This works great for consolewrite() but when I try the below to turn the array into a string I get the error " Subscript used on non-accessible variable.:"

`\$a[\$tarrow][\$i] = (\$a[\$tarrow][\$i])[0]&'/'&(\$a[\$tarrow][\$i])[1]`

I'm trying to store the array inside the array as a string, so it's not an array inside an array.

Edited by nullschritt

##### Share on other sites

Yes using a 3D array is simpler than my suggestion here:

Either way is good, and mikell's way is also good, if you do decide to store arrays inside another. So much choice! I woulld use a 3D array: new example posted in the link.

I don't see adding an extra dimension to my array affecting my problem at all(but this could just be because I'm not understanding how it would be implemented in my function). I have a 2D array, that has to remain a 2D array, but each of the values in the 2D array needs to be a fraction.

Edited by nullschritt

##### Share on other sites

The 3D array is just two arrays joined together. See my other suggestion - use 2x 2D arrays. One to store the dividends and the other to store the divisors; or use the syntax suggested by mikell. You can't view a 3D array using _ArrayDisplay(). Storing as strings was my first example in the other post. You will need to format the numbers as shown if you want to multiply the fractions later. That's not efficient.

I'll take another look tomorrow if you are still struggling by then. I have to sleep shortly.

Edited by czardas

##### Share on other sites

The 3D array is just two arrays joined together. See my other suggestion - use 2x 2D arrays. One to store the dividends and the other to store the divisors; or use the syntax suggested by mikell. You can't view a 3D array using _ArrayDisplay(). Storing as strings was my first example in the other post. You will need to format the numbers as shown if you want to multiply the fractions later. That's not efficient.

I'll take another look tomorrow if you are still struggling by then. I have to sleep shortly.

Thanks, I'm still just not sure how to implement a 3d array within my function, I understand what you're saying though, about the function being able to support fractions 100% without reformatting the output strings back into arrays.

##### Share on other sites

My best guess would be that after the _fractionsubtract is done \$a goes from a 2d to 3d array. I'd say save the 3d array values to a \$temp and redim \$a the send the values back.

Idk it very confusing. I'm trying to wrap my mind around it. Ya bc once 2D array \$a goes to the _fractionsubtract all values return with an extra dimension and your basically trying to go like this \$a [0][1]=\$a [0][1][2]....

Maybe don't need redim if you try something like

\$temp = _FractionSubtract(_fraction(number(\$a[\$tarrow][\$i])), _FractionMultiply(\$a[\$pivrow][\$i], _fraction(number(\$tarelt))))

\$a[\$tarrow][\$i] = \$temp[0] &'/'& \$temp[1]

Edited by markyrocks

##### Share on other sites

I took a look now and I still find this script rather confusing. The array variables have to be accessed correctly as shown. However the numbers are large and the types of calculation are introducing approximations. Depending on how many times approximations occur, the results may become less accurate than if you were to use floats. The test I did in the official thread only remained accurate for 29 iterations. Once there was about 20 or more accumilated approximations, the 15 digits returned using floats was more accurate than the value returned using fractions. This can actually be fixed.

Combining the Fraction UDF with large random numbers is not recommended. For example: pounds shillings and pence; or stones, pounds and ounces will remain accurate because imperial systems use measurements that are easy to divide, although such calibrations may seem an odd choice historically. The values are not likely to go out of range and these functions may be ideally suited in situations like that. Size limitations were my first thought when looking at your code earlier, otherwise I would have suggested using this UDF myself.

Your code contains more bugs, because at one point Fraction returns an error causing the code to terminate abruptly. You need to check for errors with code like this.

;

```#include "fraction.au3"
#include <array.au3>

_inv_big(\$matricies[0])

Func _inv_big(\$m)
Local \$n = UBound(\$m, 1)
Local \$a[\$n][2 * \$n]
Local \$inv[\$n][\$n]
Local \$temprow[2 * \$n]
Local \$pivelt, \$tarelt, \$pivrow, \$tarrow, \$k, \$i, \$j
#Region - Filling matrix A
For \$i = 0 To \$n - 1
For \$j = 0 To \$n - 1
\$a[\$i][\$j] = \$m[\$i][\$j]
Next
Next
For \$i = 0 To \$n - 1
\$a[\$i][\$n + \$i] = 1
Next
#EndRegion - Filling matrix A
#Region - Inverting matrix \$M

Local \$aExpression = 0
Local \$iExtended = 0

For \$pivrow = 0 To \$n - 1
\$pivelt = \$a[\$pivrow][\$pivrow]
If (\$pivelt == 0) Then
\$k = \$pivrow + 1
While (\$pivelt == 0 And \$k <= \$n)
\$pivelt = \$a[\$k][\$pivrow]
\$k = \$k + 1
WEnd
If (\$pivelt == 0) Then
SetError(1)
Return
Else
For \$i = 0 To 2 * \$n - 1
\$temprow[\$pivrow][\$i] = \$a[\$pivrow][\$i]
\$k = \$k - 1
Next
For \$i = 0 To 2 * \$n - 1
\$a[\$pivrow][\$i] = \$a[\$k][\$i]
Next
For \$i = 0 To 2 * \$n - 1
\$a[\$k][\$i] = \$temprow[\$k][\$i]
Next
EndIf
EndIf
For \$i = 0 To 2 * \$n - 1
\$a[\$pivrow][\$i] = _fraction(Number(\$a[\$pivrow][\$i]), Number(\$pivelt))

If @error Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ERROR<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

MsgBox(0, "", "ERROR" & @CRLF & (@error = 2) ? "You cannot divide by zero!" : "???")
Exit
EndIf

;array is accessable here
Next
#Region - replace all other rows by target
For \$tarrow = 0 To \$n - 1
If (\$tarrow <> \$pivrow) Then
\$tarelt = \$a[\$tarrow][\$pivrow]
For \$i = 0 To 2 * \$n - 1
\$aExpression = _FractionMultiply(\$a[\$pivrow][\$i], _fraction(Number(\$tarelt)))
;If @error Then MsgBox(0, "", "ERROR = " & @error)
If @extended Then \$iExtended += 1 ; Approximation used
\$a[\$tarrow][\$i] = _FractionSubtract(_fraction(Number(\$a[\$tarrow][\$i])), \$aExpression)
If @extended Then \$iExtended += 1 ; Approximation used
;If @error Then MsgBox(0, "", "ERROR = " & @error)
;_ArrayDisplay(\$a[\$tarrow][\$i])
;array is accessable here via _arraydisplay() but when I try to consolewrite the values it says the dimension range is exceeded
ConsoleWrite((\$a[\$tarrow][\$i])[0] & '/' & (\$a[\$tarrow][\$i])[1] & " - Approximations = " & \$iExtended & @CRLF)
\$iExtended = 0
Next
EndIf
Next
;array is accessable here with _arraydisplay but still not via any other method
#EndRegion - replace all other rows by target
Next
_ArrayDisplay(\$a)
;array is nullified, all values for the array get set to 1
#Region - finally extract the inverse from columns N+1 to 2N
For \$i = 0 To \$n - 1
For \$j = 0 To \$n - 1
\$inv[\$i][\$j] = \$a[\$i][\$n + \$j]
Next
Next
#EndRegion - finally extract the inverse from columns N+1 to 2N
Return \$inv
#EndRegion - Inverting matrix \$M
EndFunc   ;==>_inv_big

Func _datagen()
Local \$ret
For \$i = 1 To 112
Local \$data = ""
For \$x = 0 To 7
For \$y = 0 To 7
\$data &= Random(111111111, 99999999999, 1) & ","
Next
\$data = StringTrimRight(\$data, 1) & "/"
Next
\$ret &= StringTrimRight(\$data, 1) & "|"
Next
Return \$ret
EndFunc   ;==>_datagen

Local \$dataz[\$z]
\$array = StringSplit(\$data, "|")
If \$array[0] < \$z - 1 Then Return 0
For \$i = 0 To \$z - 1
\$dataz[\$i] = _stringtoarray(\$data, \$i)
If \$dataz[\$i] = 0 Then
Return 0
EndIf
Next
Return \$dataz

Func _stringtoarray(\$data, \$n = 0)
\$array = StringSplit(\$data, "|", 2)
\$next = StringSplit(\$array[\$n], "/")
\$num2 = StringSplit(\$next[1], ",")
Local \$ar1[\$next[0]][\$num2[0]]
For \$i2 = 1 To \$next[0]
\$next2 = StringSplit(\$next[\$i2], ",", 2)
For \$i3 = 0 To UBound(\$next2) - 1
If \$i2 - 1 > \$next[0] - 1 Or \$i3 > \$num2[0] - 1 Or \$i3 > UBound(\$next2) Then
Return 0
EndIf
\$ar1[\$i2 - 1][\$i3] = \$next2[\$i3]
Next
Next
Return \$ar1
EndFunc   ;==>_stringtoarray```

;

Console output before the crash:

```0/1 - Approximations = 0
-380359654586940/446927 - Approximations = 1
171968865510555/287359 - Approximations = 2
-30656635528634/72801 - Approximations = 1
-8477385642562/23011 - Approximations = 1
636068037372/17107 - Approximations = 1
-156304644584205/150437 - Approximations = 1
-150536495218099/127802 - Approximations = 1
-1125373156/851252925 - Approximations = 0
1/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
-23682266742432/86209 - Approximations = 1
384201597749587/376965 - Approximations = 1
737142401693815/1022201 - Approximations = 1
-284674634303966/591759 - Approximations = 1
82166046046895/638798 - Approximations = 1
-41197517165269/241768 - Approximations = 1
-99842562869633/650417 - Approximations = 1
-538653187/851252925 - Approximations = 0
0/1 - Approximations = 0
1/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
134305155576051/716341 - Approximations = 1
-13203556738853/366200 - Approximations = 1
-24537672922118/82847 - Approximations = 1
16549480276482/195259 - Approximations = 1
318078124453980/649507 - Approximations = 1
-134672668171525/259953 - Approximations = 1
-177826968340988/360917 - Approximations = 1
-644567516/851252925 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
1/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
-3310742175483/10937 - Approximations = 1
38089339644151/44367 - Approximations = 2
-588517529215595/1467409 - Approximations = 1
26788526946040/434317 - Approximations = 1
-271720930109587/1703199 - Approximations = 1
50331968209596/229393 - Approximations = 1
31282761152975/503227 - Approximations = 1
-722347028/851252925 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
1/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
55223044767624/590287 - Approximations = 1
792481985903750/1639089 - Approximations = 2
21188682029327/57991 - Approximations = 1
121391497317435/1314869 - Approximations = 1
100882937820783/795179 - Approximations = 1
147943467335954/248541 - Approximations = 1
146343665474686/766673 - Approximations = 1
-22422524/56750195 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
1/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
-442828109356372/1138553 - Approximations = 1
148562416952300/233567 - Approximations = 2
64747470414887/90667 - Approximations = 1
-472192450868331/973469 - Approximations = 1
56787182225178/183551 - Approximations = 1
-61522571017139/174597 - Approximations = 1
-80358143448662/189973 - Approximations = 1
-511305061/851252925 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
1/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
-655534122402960/831419 - Approximations = 1
159430988842190/154787 - Approximations = 2
590543215316390/1006671 - Approximations = 1
-410456341802942/743569 - Approximations = 1
-308038049824643/1022112 - Approximations = 1
-26671328141969/242773 - Approximations = 1
-43038389523744/643837 - Approximations = 1
-129455192/170250585 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
0/1 - Approximations = 0
1/1 - Approximations = 0```
Edited by czardas

##### Share on other sites

Then I guess I'm just plain not understanding how to use the fractions UDF.

Because I litterally replaced all normal math operations with your fractions version.

The version without fractions uses the exact same operations.... it should never try to divide by zero.... or I would experience the same failure when using the regular arithmetic operations...

It may try to divide by a decimal at some point, so could this be the problem? does your function fail to process 0.nnnnn ?

But as I understand using the fractions UDF to process my doubles, will still provide a more accurate end result after several iterations, so when I converted the final fractions back into doubles they would be more accurate than running several iterations of regular division of doubles over and over.

I have feeling that inaccuracies in my compression algorithm are to blame on this one function, because with each iteration the numbers become more and more inaccurate.

Edited by nullschritt

##### Share on other sites

Okay, I added in line to check to see if it was dividing by zero, and now it returns what I want. A 2D array containing all the fractions as sub-arrays.

But now I'm super confused as to my next step.

I need to allow my function to accept fractions or numbers as input, because this function has several iterations run on it, and the input of each is the output of the last, so the first time we input numbers and it returns an array of fractions, that much I've got down, but is it then possible to accept an array of fractions and preform the same operations on the fractions as if they were numbers, like 100/48 / 30/60 (dividing one fraction by another, or multiplying one fraction by another). Im sorry if I seem slow to pick up, I just don't fully understand your fractions UDF, and I don't recall how operations on fractions work from school.

Here's my code that works now:

```#include "fractions.au3"
#include <array.au3>

_inv_big(\$matricies[0])

Func _inv_big(\$m)
Local \$n = UBound(\$m, 1)
Local \$a[\$n][2 * \$n]
Local \$inv[\$n][\$n]
Local \$temprow[2 * \$n]
Local \$pivelt, \$tarelt, \$pivrow, \$tarrow, \$k, \$i, \$j
#Region - Filling matrix A
For \$i = 0 To \$n - 1
For \$j = 0 To \$n - 1
\$a[\$i][\$j] = \$m[\$i][\$j]
Next
Next
For \$i = 0 To \$n - 1
\$a[\$i][\$n + \$i] = 1
Next
#EndRegion - Filling matrix A
#Region - Inverting matrix \$M

Local \$aExpression = 0
Local \$iExtended = 0

For \$pivrow = 0 To \$n - 1
\$pivelt = \$a[\$pivrow][\$pivrow]
If (\$pivelt == 0) Then
\$k = \$pivrow + 1
While (\$pivelt == 0 And \$k <= \$n)
\$pivelt = \$a[\$k][\$pivrow]
\$k = \$k + 1
WEnd
If (\$pivelt == 0) Then
SetError(1)
Return
Else
For \$i = 0 To 2 * \$n - 1
\$temprow[\$pivrow][\$i] = \$a[\$pivrow][\$i]
\$k = \$k - 1
Next
For \$i = 0 To 2 * \$n - 1
\$a[\$pivrow][\$i] = \$a[\$k][\$i]
Next
For \$i = 0 To 2 * \$n - 1
\$a[\$k][\$i] = \$temprow[\$k][\$i]
Next
EndIf
EndIf
For \$i = 0 To 2 * \$n - 1
if Number(\$pivelt) <> 0 Then
\$a[\$pivrow][\$i] = _fraction(Number(\$a[\$pivrow][\$i]), Number(\$pivelt))
EndIf
If @error Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ERROR<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

MsgBox(0, \$pivelt, "ERROR" & @CRLF & (@error = 2) ? "You cannot divide by zero!" : "???")
Exit
EndIf

;array is accessable here
Next
#Region - replace all other rows by target
For \$tarrow = 0 To \$n - 1
If (\$tarrow <> \$pivrow) Then
\$tarelt = \$a[\$tarrow][\$pivrow]
For \$i = 0 To 2 * \$n - 1
\$aExpression = _FractionMultiply(\$a[\$pivrow][\$i], _fraction(Number(\$tarelt)))
;If @error Then MsgBox(0, "", "ERROR = " & @error)
If @extended Then \$iExtended += 1 ; Approximation used
\$a[\$tarrow][\$i] = _FractionSubtract(_fraction(Number(\$a[\$tarrow][\$i])), \$aExpression)
If @extended Then \$iExtended += 1 ; Approximation used
;If @error Then MsgBox(0, "", "ERROR = " & @error)
;_ArrayDisplay(\$a[\$tarrow][\$i])
ConsoleWrite((\$a[\$tarrow][\$i])[0] & '/' & (\$a[\$tarrow][\$i])[1] & " - Approximations = " & \$iExtended & @CRLF)
\$iExtended = 0
Next
EndIf
Next
#EndRegion - replace all other rows by target
Next
_ArrayDisplay(\$a[0][0])
;array is okay
#Region - finally extract the inverse from columns N+1 to 2N
For \$i = 0 To \$n - 1
For \$j = 0 To \$n - 1
\$inv[\$i][\$j] = \$a[\$i][\$n + \$j]
Next
Next
#EndRegion - finally extract the inverse from columns N+1 to 2N
Return \$inv
#EndRegion - Inverting matrix \$M
EndFunc   ;==>_inv_big

Func _datagen()
Local \$ret
For \$i = 1 To 112
Local \$data = ""
For \$x = 0 To 7
For \$y = 0 To 7
\$data &= Random(111111111, 99999999999, 1) & ","
Next
\$data = StringTrimRight(\$data, 1) & "/"
Next
\$ret &= StringTrimRight(\$data, 1) & "|"
Next
Return \$ret
EndFunc   ;==>_datagen

Local \$dataz[\$z]
\$array = StringSplit(\$data, "|")
If \$array[0] < \$z - 1 Then Return 0
For \$i = 0 To \$z - 1
\$dataz[\$i] = _stringtoarray(\$data, \$i)
If \$dataz[\$i] = 0 Then
Return 0
EndIf
Next
Return \$dataz

Func _stringtoarray(\$data, \$n = 0)
\$array = StringSplit(\$data, "|", 2)
\$next = StringSplit(\$array[\$n], "/")
\$num2 = StringSplit(\$next[1], ",")
Local \$ar1[\$next[0]][\$num2[0]]
For \$i2 = 1 To \$next[0]
\$next2 = StringSplit(\$next[\$i2], ",", 2)
For \$i3 = 0 To UBound(\$next2) - 1
If \$i2 - 1 > \$next[0] - 1 Or \$i3 > \$num2[0] - 1 Or \$i3 > UBound(\$next2) Then
Return 0
EndIf
\$ar1[\$i2 - 1][\$i3] = \$next2[\$i3]
Next
Next
Return \$ar1
EndFunc   ;==>_stringtoarray```

##### Share on other sites

I haven't done extensive testing on the UDF. It seems you are quickly ending up with a lot of 15 digit numbers so approximations will occur. To add, multiply, subtract or divide; the divisors have to be multiplied together. If the result does not factorize easily then the numbers will remain large.

;

Fraction1 = Fraction2 / Fraction3

`\$a1 = _FractionDivide(\$a2, \$a3) ; Returns a fraction`

;

_Fraction(0.0001) works fine. If at some point I get the UDF to work with two Int64 values, it will always beat Double Precision for accuracy, hands down.

Never divide by zero!

Edited by czardas

##### Share on other sites

Also finding now that my algorithm isn't working properly, because the places where it wants to divide by zero are placeholders for re-arranging the data.

Just now realized that the output array now contains all the placeholders and the values. Gosh this is becoming a bit of a headache.

##### Share on other sites

LOL, I could have told you where the zeros were coming from. You need to go through every step carefully. I always make a scaled down version covering every step of a complex process. I write lots of comments to remind myself what I was thinking at the time, or why I changed something. I know the limitations of my UDF and I'm still unsure if it is adequate for this. As I said; the limitations may only be temporary, but fine tuning for greater accuracy will take time.

One more thing to be careful of (check for errors) is fraction approximation to zero ==> 0/1. The smallest value is:

1/999999999999999

Anything smaller than 1/1999999999999998 becomes zero.

Edited by czardas

##### Share on other sites

Is there any way you could take a look at the function and maybe comment in what I need to change to make it function with strictly fractions? Converting my original input to fractions then the final output to decimal wouldn't be that difficult.

But I didn't code this function and I can't remember who did, and I'm having a really hard time grasping how to make it operate using functions in place of integers.

If you could find the time to show me what I'm doing wrong I would greatly appreciate it, I'm thinking it has something to do with the function not properly detecting the 1/0 and 0/1 when re-arranging the data as it's originally been coded to check ints not fraction.

This is what the function is attempting to achieve

The first matrix(array) is the original, and the second is it's inverse, so this function is trying to take the original set of data and "inverse" it.

But this function has been designed to work with numbers, not fractions, but it's completley possible to use fractions inside of a matrix, I just have no real education with how fractions work, and so I'm over here scratching my head like an idiot trying to wonder how to get the function to properly re-arrange the data, it's properly generating the inverse fractions of the input fractions, but it's confused about how to resort the data because the placeholder digits are now fractions instead of ints :/

Edit: and I'm also guessing I would have to allow the fractions udf to divide by zero, since there's no actual dividing by zero going on, as those are just empty placeholders, to be disposed of.

Edited by nullschritt

##### Share on other sites

Well it's the first time I've looked at matrix inversion. To be honest I'd need time to study this which I don't have. If you don't understand the code you posted, that makes two of us I'm afraid.

I took a quick look here:

http://mathworld.wolfram.com/MatrixInverse.html

##### Share on other sites

I guess I'll have to give up for now and move on to other more pressing features of my project. I already have a feature that automatically corrects corrupted data by reprocessing it, and this is still several hundred times faster than using bignum to get an accurate result.

You functions UDF seemed a lot more lightweight, and to be honest, I'm not 100% sure it would completely fix the corruption, I was simply hoping that it might improve the percentage of the time that the output came out correct by reducing the inaccuracies in autoit-its handling of doubles.

##### Share on other sites

When you get the time could you write a version of the _fraction() function that accepts values to be divided by zero(since your function isn't actually preforming the division)? At least then I would be able to store all the appropriate values in the array, then I would just have to figure out what part of the function needs those values.

##### Share on other sites

I wouldn't give up on it altogether. Sometimes taking a step back gives you more perspective. In all honesty I'm reasonably happy with the UDF, but not quite as happy as I originally wanted to be.

Regarding division by zero. You can do it as much as you like using _Fraction() so long as you do not try and access the non-existent array afterwards. That's where the interpreter throws an error. The same applies with numbers: after division by zero infinity is returned (or rather a representation of infinity) and AutoIt does not throw an error. Of course it's wrong to divide by zero in both cases and I have no intentions of overriding the current behaviour. All the checks you need are already provided.

##### Share on other sites

Here a fast hack for a 2x2 matrix:

```;a fast hack version by UEZ
#include <Array.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>

Global \$hGUI = GUICreate("2x2 Matrix Invers", 500, 306, -1, -1)
Global \$iLabel = GUICtrlCreateLabel("2x2 Matrix Invers", 40, 20, 400, 40, \$SS_CENTER)
GUICtrlSetFont(-1, 20, 400, 0, "Arial", 5)
Global \$hLabel2 = GUICtrlCreateLabel("Matrix A", 80, 90, 100, 28, \$SS_CENTER)
GUICtrlSetFont(-1, 20, 400, 0, "Times New Roman", 5)
Global \$iInput_A = GUICtrlCreateInput("4.25", 80, 130, 40, 30, \$SS_CENTER)
Global \$iInput_B = GUICtrlCreateInput("7/2", 130, 130, 40, 30, \$SS_CENTER)
Global \$iInput_C = GUICtrlCreateInput("3", 80, 165, 40, 30, \$SS_CENTER)
Global \$iInput_D = GUICtrlCreateInput("2", 130, 165, 40, 30, \$SS_CENTER)
Global \$hLabel3 = GUICtrlCreateLabel("Matrix A'", 280, 90, 100, 28, \$SS_CENTER)
GUICtrlSetFont(-1, 20, 400, 0, "Times New Roman", 5)
Global \$iInput_Ai = GUICtrlCreateInput("", 280, 130, 100, 30, BitOR(\$ES_READONLY, \$SS_CENTER))
Global \$iInput_Bi = GUICtrlCreateInput("", 390, 130, 100, 30, BitOR(\$ES_READONLY, \$SS_CENTER))
Global \$iInput_Ci = GUICtrlCreateInput("", 280, 165, 100, 30, BitOR(\$ES_READONLY, \$SS_CENTER))
Global \$iInput_Di = GUICtrlCreateInput("", 390, 165, 100, 30, BitOR(\$ES_READONLY, \$SS_CENTER))
Global \$iButton = GUICtrlCreateButton("Calculate", 280, 230, 90, 60)
GUISetState()

While 1
Switch GUIGetMsg()
Case \$GUI_EVENT_CLOSE
GUIDelete()
Exit
Case \$iButton
Calc_InversMatrix()
EndSwitch
WEnd

Func Calc_InversMatrix()
If Not \$aMatrix[1][0] And Not \$aMatrix[1][1] Then Return SetError(1, 0, 0) ; -> determinant is zero, therefore inverse matrix doesn't exist
Local \$fDetA = 1 / (\$aMatrix[0][0] * \$aMatrix[1][1] - \$aMatrix[1][0] * \$aMatrix[0][1]), \$f
\$f = Number(\$fDetA * \$aMatrix[1][1])
GUICtrlSetData(\$iInput_Ai, Float2Frac(\$f))
GUICtrlSetTip(\$iInput_Ai, \$f)
\$f = Number(\$fDetA * -\$aMatrix[0][1])
GUICtrlSetData(\$iInput_Bi, Float2Frac(\$f))
GUICtrlSetTip(\$iInput_Bi, \$f)
\$f = Number(\$fDetA * -\$aMatrix[1][0])
GUICtrlSetData(\$iInput_Ci, Float2Frac(\$f))
GUICtrlSetTip(\$iInput_Ci, \$f)
\$f = Number(\$fDetA * \$aMatrix[0][0])
GUICtrlSetData(\$iInput_Di, Float2Frac(\$f))
GUICtrlSetTip(\$iInput_Di, \$f)
EndFunc   ;==>Calc_InversMatrix

Func Float2Frac(\$fFloat, \$iAccuracy = 5) ;coded by UEZ
If Not IsNumber(\$fFloat) Then Return SetError(1, 0, 0)
Local \$iDec = StringLen(StringRegExpReplace(\$fFloat, "\d+\.(\d*)", "\1"))
\$iAccuracy = \$iAccuracy > 10 ? 10 : \$iAccuracy
\$iDec = \$iDec > \$iAccuracy ? \$iAccuracy : \$iDec
Local \$iZaehler = Round(\$fFloat * 10 ^ \$iDec, 0)
Local \$iNenner = 10 ^ \$iDec
Local \$iGGT = Number(ggT(Int(\$iZaehler), Int(\$iNenner)))
ConsoleWrite("Float: " & \$fFloat & @CRLF)
ConsoleWrite("Dec: " & \$iDec & @CRLF)
ConsoleWrite("Zaehler: " & \$iZaehler & @CRLF)
ConsoleWrite("Nenner: " & \$iNenner & @CRLF)
ConsoleWrite("\$iGGT: " & \$iGGT & @CRLF)
ConsoleWrite(\$fFloat & " -> " & \$iZaehler / \$iGGT & " / " & \$iNenner / \$iGGT & @CRLF & @CRLF)
If \$iGGT < 0 Then
\$iZaehler /= \$iGGT * -1
\$iNenner /= \$iGGT * -1
Else
\$iZaehler /= \$iGGT
\$iNenner /= \$iGGT
EndIf
Return \$iZaehler & " / " & \$iNenner
EndFunc   ;==>Float2Frac

Func ggT(\$a, \$b) ;coded by UEZ 2012
If Not IsInt(\$a) Then Return SetError(1, 0, 0)
If Not IsInt(\$b) Then Return SetError(2, 0, 0)
If \$a = \$b Then Return Abs(\$a)
If Not \$a And \$b Then Return Abs(\$a)
If \$a And Not \$b Then Return Abs(\$b)
If (\$a And \$b = 1) Or (\$a = 1 And \$b) Then Return 1
Local \$iMod
Do
\$iMod = Mod(\$a, \$b)
If Not \$iMod Then ExitLoop
\$a = \$b
\$b = \$iMod
Until False
Return \$b
EndFunc   ;==>ggT```
Edited by UEZ

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

## Create an account

Register a new account

• ### Recently Browsing   0 members

×

• Wiki

• Back

• #### Beta

• Git
• FAQ
• Our Picks
×
• Create New...