Jump to content

Recommended Posts

I'm looking for a way to compare any given number and return the array value that is closest to it. Is there a specific function that can do this or do I have to come up with my own method?

Here's the basic code.

Global Const $aE12[13] = [12, 1, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2]

Local $iNumber = 4

For $i = 1 To $aE12[0]
    ; Do comparison and
    ; Return closest value
Next

Edit: Also, if the given number happens to be exactly between two array values, the first array value should be returned.

If you could manage to avoid storing the array "useful size" in the 0-th array element and have your values sorted, that would greatly help!

Also "exactly" has to be taken lightly when talking about floating point.

Since your interest is in the closest value (not its index), do that: remove element 0 then arraysort if needed then compare until ... your conditions are met.

Try to come up with something that work as a "paper machine"; then translating into AutoIt should be a piece of cake.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Okay, this is the fully working solution that I came up with.

#include <Array.au3>

Global Const $aPrefer[13] = [12, 1, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2]

Local $sValue = 4.6
Local $aResults[$aPrefer[0] + 1] = [$aPrefer[0]]
For $i = 1 To $aPrefer[0]
    $aResults[$i] = StringReplace($sValue - $aPrefer[$i], "-", "")
Next

_ArrayDisplay($aResults)

MsgBox(0, "", $aPrefer[_ArrayMinIndex($aResults, 1, 1)])

Sorry but this code is a bit ugly. Please don't take offence! Why use another array and go thru the value and then again thru the differences? You only need to store the least difference found at a given step, not all of them.

A cleaner way, relying on values being sorted:

Global Const $aPrefer[13] = [12, 1, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2]
Local $sValue = 4.6
Local $nResult = $aPrefer[UBound($aPrefer) - 1]
For $i = 1 To UBound($aPrefer) - 2
    If Abs($aPrefer[$i] - $sValue) <= Abs($aPrefer[$i + 1] - $sValue) Then
        $nResult = $aPrefer[$i]
        ExitLoop
    EndIf
Next
MsgBox(0, "Value with Least Difference", "Best approximation to " & $sValue & " is " & $nResult)

Can be adapted for unsorted values as well (use another variable to hold the least difference found in absolute value and initialize it with the abs. diff with the last item, then don't exit your loop early). I leave you the details. Even if you may say this is of little importance in the case at hand, I find it better to use the right approach every time, to avoid bad habits and have code well written in case the difference really matters. Always suppose your table of values has 100 million elements!

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

I do have a bad habit of using the first working result instead of looking for the best.

Well I'd say the question isn't really to aim at "the best" implementation every time. This would cause a great lot of lengthy interrogations about writing about anything useful. The direction is more towards clean code with "decently fit" data structures. It makes your code more modular (in a vague sense) and certainly dramatically easier to maintain, by you as well as by others.

Using your original question as support, if you read the unsorted version below in plain naural language, you "see" that it fits almost exactly your statements. Of course this is no substitute to a formal proof of correctness, but it's certainly much better than insightful-less code hastily writen and painfully "patched" until it seems to work (most of the time, without proper testing of boundaries values etc.)

Devoting some time to think about a problem _before_ rushing to code, 99% of the time pays back in the middle term and 300% in the long run. And again, I'm not being pedantic, only stating the truth that applies to anyone, including myself. At times I also am lazy and says to me "this doesn't matter for the case I'm dealing with, so quick'n really dirty will do". Almost invariably this turns out to be a bad idea, requiring sooner or later twice more time to debug / clean / correct / fix.

Global Const $aPrefer[13] = [12, 1, 2.2, 5.6, 6.8, 2.7, 3.3, 3.9, 1.2, 1.5, 1.8, 4.7, 8.2]
Local $nValue = 4.6

Local $nResult = $aPrefer[UBound($aPrefer) - 1]
Local $nLeastDiff = Abs($aPrefer[UBound($aPrefer) - 1] - $nValue)

For $i = 1 To UBound($aPrefer) - 2
    If Abs($aPrefer[$i] - $nValue) <= $nLeastDiff Then
        $nResult = $aPrefer[$i]
        $nLeastDiff = Abs($aPrefer[$i] - $nValue)
    EndIf
Next
MsgBox(0, "Closest value", "Best approximation to " & $nValue & " is " & $nResult)

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...