SQLite SUM function rounding error - android - android

Why is it that when I call a SUM on one of my SQLite columns, it doesnt return a precise answer? Heres what I mean:
Lets say I have 4 rows in my column to sum
row1 8362.82
row2 +18837.42
row3 +7294.12
row4 +73.23
___________________
17567.59
Now these should add up to 17567.59 right? Well my sum returns 17567.6. This may not sound like a big deal but I need accurate decimals, not rounded ones. It rounds further as the numbers get larger too. Can anyone explain a solution to this? Thanks.

Store the values as integers instead of floats.

I had the same roundoff problem, except mine were rounding to integers instead of maintaining one place after the decimal point. I switched to using total() instead of sum().
From the documentation:
The result of total() is always a floating point value. The result of
sum() is an integer value if all non-NULL inputs are integers. If any
input to sum() is neither an integer or a NULL then sum() returns a
floating point value which might be an approximation to the true sum.
This doesn't explain the issue in my case, because my column contained a mix of integer and floating-point values. But I decided to try it because of the difference, and it worked. It also sums all NULLs to 0 instead of NULL which is useful in many cases.

Related

Android: regex for edit text to have only 2 values possible in decimal

In my filter used into EditText, I want to be sure the user can only set .5 or .0 for decimal values.
Valid values examples:
34.5
34.0
34
Invalid values examples:
34.2
34.8
34.6
I tried this one, but it doesn't work properly: [0-9]*[.]?[0|5]
Thank you very much guys!
You're probably looking for [0-9]*(\.([50][0]*)*)*.
[0-9]*: Any character from 0 to 9, zero or more times [so that just a "." (= 0.0) input is valid]
\.: You need to escape the '.' character, since it usually would mean "any character", and you especifically need the dot there.
[50][0]*: First, either five or zero (once). Second, the 0 character, zero or more times (since 35.50 = 35.5). This also avoids inputs like 35.59 from being valid, since 9 != 0.
([50][0]*)*: This occurrence zero or more times, so that 35., for instance, becomes a valid input (since 35. = 35.0).
(\.([50][0]*)*)*: As for this grouping, it's in order to check for the five or the zero only if there is a decimal dot. It's grouping the dot character and the 5/0 logic together with a star (zero or more times) at the end, so if it doesn't occur, it still matches.
Let me know if this was what you were looking for.
To verify the whole numbers in the examples, you can make the last part optional and use anchors.
^[0-9]+(?:[.][05])?$
^ Start of string
[0-9]+ Match 1+ digits 0-9
(?:[.][05])? Optionally match . and a digit 0 or 5
$ End of string
See a regex demo.
If you want to be able to only type a pattern like that and also accept empty strings or 34. you can repeat the digit 0 or more times, optionally match . and optionally match either 0 or 5.
^[0-9]*[.]?[05]?$
See another regex demo

How to implement FNV-1(a) in SQLite?

(Moved from https://softwareengineering.stackexchange.com/questions/406813/how-to-implement-fnv-1a-in-sqlite)
I'm trying to modify a SQLite query (in Android) to return its results in pseudorandom order. As in this question, the order needs to be stable over repeated queries (e.g. due to paging, screen rotation, etc.), so I can't just use ORDER BY RANDOM(). Instead I want to use a hash function that depends on a couple of input values that provide stability and sufficient uniqueness. (One of these values is a unique ID column of the table, which is a set of integers fairly close together; the other value is more like an session ID, also an integer, that remains invariant within this query.)
According to this well-researched answer, FNV-1 and FNV-1a are simple hash functions with few collisions and good distribution. But as simple as they are, FNV-1 and FNV-1a both involve XOR operations, as well as looping over the bytes of input.
Looping within each row of a query is pretty awkward. One could fake it by unrolling the loop, especially if only a few bytes are involved. I could make do with two bytes, combining LSBs from the two input values (val1 & 255 and val2 & 255).
XOR isn't supported directly in SQLite. I understand A ^ B can be implemented as (A | B) - (A & B). But the repetition of values, combined with the unrolling of the loop, starts to get unwieldy. Could I just use + (ignoring overflow) instead of XOR? I don't need very high quality randomness. The order just needs to look random to a casual observer over small-integer scales.
So I'm wondering if anyone has already implemented such a thing. Given how widely used this hash function is, it seems like there would likely already be an implementation for this situation.
Here's my attempt at implementing FNV-1a:
SELECT ..... ORDER BY (((fnvbasis + val1 & 255) * fnvprime) + val2 & 255) * fnvprime % range;
I'm ignoring the fact that in FNV, the XOR operation (which I've replaced with +) is only supposed to affect the lowest 8 bits of the hash value. I'm also ignoring any overflow (which I hope just means the upper bits, which I don't care about, are lost).
For fnvbasis I'll use 16777619, and for fnvprime I'll use 2166136261. These are the specified values for 32 bit input, since I don't see a specified value for 16 bit input. For range I'll use a prime number that's greater than the expected number of rows returned by this query.
So is this a reasonable way to approximate FNV-1a in a SQLite query? Is there a better, existing implementation? I.e. will it actually produce an ordering that looks pretty random to a casual user, despite my mutilating the operations of the real FNV-1a?
Inspired by comments from rwong and GrandmasterB on the previous attempt at this question before I moved it, I decided I could precompute the first iteration of FNV-1a's loop, i.e. the hash based on the unique ID column of the table. The precomputed column, fnv1a_step1, is set to
(fnvbasis ^ (ID & 0xFF)) * fnvprime
Because this value is precomputed on each row of the table separately, it can be supplied by the app and doesn't need to be expressed in SQLite; hence the use of ^ (XOR) above. Also, if ID is a string, we can compute an 8-bit hash value from it in Java or Kotlin as well. But we could even use
(fnvbasis + (RANDOM() & 0xFF)) * fnvprime
(back to using + if doing this in SQLite) because the value is only computed once, and therefore is stable even when computed from RANDOM().
The second iteration of the FNV-1a loop can be computed pretty simply in the ORDER BY clause of the query, using the current session ID, so it produces a different-but-stable ordering for each session:
ORDER BY (fnv1a_step1 + sessionId & 0xFF) * fnvprime % range;
I've implemented this in my app, and it seems to work, to my requirements. The order is stable within a session, but is different in each session.

OpenCV Android - Calculate the average of a column of Mat

What I'm trying is to calculate the average of a column using openCV in android.
The initial idea was to copy each column to a temp matrix, then use Core.mean() to get the average value.
But the problem is :
To use Mat.put(), it is expected to have a row, column and a Array[] data and Core.Mean() returns a scalar, so I can't do something like:
myMat.put(row,1,Core.Mean(myTempColumn)).
So how this operation can be done?
I'm wondering that I'll need to get each element from myMat using get and then sum. But the problem is get returns also a Array[] data (that I think is the RGB value), and to sum it, will be necessary another for structure (which I don't think it is the easiest way).
Thank you in advance.
Ok solve it:
Core.reduce(imageMat,averageMat,0,Core.REDUCE_AVG);
Where:
0 means that the matrix is reduced to a single row. 1 means that the matrix is reduced to a single column.
Core.REDUCE_AVG - does the average

Partial comparison of 2 strings

I'm looking for a way to compare 2 strings partial. I need to clear this with an example.
The base string is "equality".
The string I need to check is spelled wrong: "equallaty". I want to conform this is partially correct so the input, even not right in a grammar way, is the same as the base string.
Now I can of course parse the string to an char array. Now I can check every single character, but if I check the first 4 characters they will be right, the rest will be wrong even if there are only 2 mistakes. So the check I want to use is that a minimum of 70 procent of the characters should match.
Is anyone able to help me get on the right track?
Compare the strings with an edit-distance metric like the Levenshtein distance. Such a metric basically counts the number of changes needed to make the strings equal. If the number of changes is small relative to the total size of the string, then you can consider the strings similar.

storing double values in SQLite: how to ensure precision?

i have a problem with double values i need to store in an android homed sqlite database. since these double values represent gps values (lat & lng), i really NEED an absolute precision down to the 9th number after the comma.
now i have a table like this:
CREATE TABLE x REAL lng;
and insert sth (hardcoded) like:
INSERT INTO x lng = '1.0';
and when reading lng from this table into some (java) double variable, i get a value like "0.999956837" - this renders the values pretty useless to me.
is there a way to enforce the precision i need other than storing the values as "text" fields (what would make expensive casts neccessary) or storing them as integers (meaning i need to multiply/divide at each write/read-op)?
SQLite is typeless, that means all representation is written as text, probably the wrapper api does some converts you don't know of, that you get those results.
If you need to store the data as string do it.
Just when you read out the double make sure you saved in the right format, you can use getDouble on the column.
double has about 17 decimal digits of precision, so if 9 digits is what you need, there should be no problem (assuming that you don't do any complex calculations on those values). Just make sure you never end up using float, because that has only about 7 digits of precision.
You should also make sure you understand how binary floating-point works, and that it will always result in seemingly "round" values becoming slightly off - which simply does not matter for most applications (including yours) as long as it happes somewhere in the 17th decimal digit. See that link also for alternatives for applications where it does matter.

Categories

Resources