bitwise comparison of large numbers - mysql

Researching the possibility of using bitwise comparison to assess what options have been selected out a possible 100 options.
now as an integer the selection of all options would require storage of an integer of 2 to the power of 99 (6E29). way beyond the limit of circa 9E18.
just as with dir permissions ( 1 = read, 2= write, 4 = execute) 1+2+4 = 7 = full access.
I would like to know which of the 100 options have been chosen by the same method.
Any advice/tips much appreciated.
NB storage will be mysql
-- EDIT --
The end goal here is to simplify a check as to what currencies a user can be paid in.
assigning values to currency like so:
Currency OptVal
GBP 1
USD 2
EUR 4
AUD 8
CAD 16
ZAR 32
and so on (there are many many currencies and more will arise through crypto currencies I'm sure)
it would then be convenient to check which currencies a user has using bitwise operators...
so if a user had currency setting of 3 only GBP and USD.
5 GBP & EUR
63 GBP,USD,EUR,AUD,CAD,ZAR
and so on - hope this clarifies the goal.
The issue is to do this in its most simplistic form of storing that integer when you have > 100 currencies. you need a value 2E(n-1) for each option and for large n this number is very large and not storable as an integer (BIGINT Max value is 18446744073709551615)

You want advice. Don't do it this way.
MySQL offers the boolean data type, which is convenient for flags. Each value does occupy one byte, so the storage will be larger than using bits.
MySQL also offers the bit() data type, where you can put together up to 64 bits. You can read about them here.
Using built-in data types is simply the right way to go. They protect your from changes of server, from upgrades on the OS, and the possibility that your application and server have different endian-ness (if you don't know what this is, then you definitely should not be thinking about bit fiddling).
The good news is that there are data types for what you want to do.

Related

Why is Binary (machine code) based off Boolean Algebra? What would happen if numbers went from 0-9 instead of 0 or 1?

I'm curious to know if it would be possible to create a computer that uses binary that can go from 0000 up to 9999 by having true and false be 1 and 0, but add numbers 2-9 to get more possibilities for numbers. Is binary code only consisting of 0's and 1's for simplicity? Is it because for some reason computers can only understand True and False?
Binary code starts with 0 (0000) and increases to 1 (0001) to 2 (0010) and 10 (1010). Could is be possible for a computer to recognize 0's and 1's but then go to 2's and other numbers? For example, 0000 = 0, 0001 = 1, 0002 = 2, 0009 = 9 then 0010 = 10, and so on.
If this isn't possible somehow, please explain why and give a general explanation of how computers work because I'm interested and want to learn more. If this isn't used because it's inefficient, please epxlain what makes it inefficient and what makes 0's and 1's more efficient.
Thank you.
I expect that it would be possible to create a computer like this but I searched online and couldn't find out why binary code can't have numbers other than 0's and 1's.
Answer to myself for future reference:
Binary is based on Boolean Algebra because it's a base 2 system, and Decimal is a base 10 system that goes from 0-9 instead of 0 or 1 like Binary which is a base 2 system. Computers easily understand binary because its based off on and off states (0 or 1) with 0 being off and 1 being on. Computers use logic gates which are composed of a multitude of transistors that use boolean logic to store data for the computer. Binary makes hardware convenient for computers. Other number systems are used for other purposes different from Binary's purpose. For example, hexadecimal is used to represent numbers that are large in a more simple way that decimal is able to, take the number one million for example,in decimal, it would be 1000000, in binary it would be 11110100001001000000, and in hexadecimal it would be F4240. This is why the Binary number system is based off boolean alegbra and why computers use binary and not other number systems.
It is based on how the data is stored. Each piece of data stored in your memory can have only two values. Think of your memory as a number of glasses which can either be empty or full. Which means the data is stored as bunch of 1s and 0s. This is the result of moving from analog systems to digital, analog values can be between 0 and 1. In analog systems for example, you can have 0.25 or 0.7. But since computers became digital, the logic became binary.
It will be really beneficial to research the history of computers and learn how they evolved over time, if you are interested in this topic.

Why is MS Access returning some results in scientific notation?

I have two fields, both have the size set to double in the table properties. When I subtract one field from the other some of the results are displayed as scientific notation when I click in the cell and others just show regular standard format to decimal places.
The data in both fields was updated with Round([Field01],2) and Round([Filed2],2) so the numbers in the fields should not be any longer than 2 decimal places.
Here's an example:
Field1 = 7.01
Field2 = 7.00
But when I subtract Field1 from Field2 the access display shows 0.01 but when I click on the result it displays, -9.99999999999979E-03. So of course, when I try to filter on all results that have 0.01 the query comes back empty because it thinks the result is -9.99999999999979E-03.
Even stranger is if Field1 = 1.02 and Field2 = 1.00, the result is 0.02 and when I click on the result the display still shows 0.02 and I can filter on all results that equal 0.02.
Why would MS Access treat numbers in the same query differently? Why is it displaying in Scientific Notation and not filtering?
Thanks for any support.
Take this simple code in Access (or even Excel) and run it!
Public Sub TestAdd()
Dim MyNumber As Single
Dim I As Integer
For I = 1 To 10
MyNumber = MyNumber + 1.01
Debug.Print MyNumber
Next I
End Sub
Here is the output of the above:
1.01
2.02
3.03
4.04
5.05
6.06
7.070001
8.080001
9.090001
10.1
You can see that after just 7 additions rounding is occurring!
Note how after JUST 7 simple little additions Access is now spitting out wrong numbers and has rounding errors!
More amazing? The above code runs the SAME in Excel!
Ok, I am sure I have your attention now!
If I recall, the FIRST day and first class in computing science? Computers don't store exact numbers when using floating point numbers.
So, then how is it possible that the WHOLE business community using Excel, or Access, or in fact your desktop calculator not come crashing down?
You mean Access cannot add up 7 simple little numbers without having errors?
How can I even do payroll then?
The basic concept and ALL you need to know here is that computers store real (floating) numbers only as approximate.
And integer values are stored exact.
so, there are several approaches here, and in fact if you writing ANY business software that needs to work with money values? And not suffer rounding errors?
Then you better off to choose what we called some kind of "scaled" integer. Behind the scenes, the computer does NOT use floating numbers, but uses a integer value, and the also has a "decimal" position.
In fact, in a lot of older business BASIC languages, or others? We often had to do the scaling on our own. (so, we would choose a large integer format). In fact, this "scaling" feature still exists in Access!!! (and you see it in the format options).
So, two choices here. If you don't want "tiny" rounding errors, then use "currency" data type. This may, or may not be sufficient for you, since it only allows a max of 4 decimal places. But in most cases, it should suffice. And if you need "more" decimal places, then you can multiply the values by 1000, and then divide by 1000 when done the calculations.
however, try changing the column type to currency and that should work. (this type of data is how your desktop calculator also works - and thus you not see funny rounding errors as a result (in most cases).
but, the FIRST rule of the day? First computer course?
Computers do not store exact numbers for floating point numbers - they are approximations, and are subject to rounding errors. Now, if you really are using double for the table, then I don't think these rounding errors should show up - since you have "so many decimal places" available.
But, I would try using currency data type - it is a scaled integer, or so called packed decimal.
You can ALSO choose to use a packed decimal in Access, and it supports out to 28 digits, and you can set the "scale" (the decimal point location). However, since you can't declare a decimal type in VBA, then I would suggest that in the table (and in VBA code, use currency data types).
If you need more then 4 decimal points, then consider scaling the currency in your code, or perhaps at that point, you consider using a packed decimal type in the table, but values in VBA will have to use the "variant" type, and they will correctly take on the data column setting if used in code and assigned a value from the table(s) in question.
Needless to say, the first day you start dealing with computers, and that first day ANYTHING beyond being a "end user"? Well, this is your first lesson of the day!
"The data in both fields was updated with Round([Field01],2) and Round([Filed2],2) so the numbers in the fields should not be any longer than 2 decimal places." instead of rounding up(which i think is the reason for the scientific notation) you can use number field as data type , then under field size choose double, then under decimal places choose 2.

Should I use 'Currency' data type in access?

For storing monetary values in MS Access I have 3 options:
Number Double
Number Decimal
Currency
Should I use the last? Or Decimal?
I wonder if this and this applies to Access?
You don’t want to use double, since Excel or Access when using such floating numbers will cause all kinds of rounding errors.
This code demonstrates this issue rather well:
Public Sub TestAdd()
Dim MyNumber As Single
Dim I As Integer
For I = 1 To 10
MyNumber = MyNumber + 1.01
Debug.Print MyNumber
Next I
End Sub
Here is the output of the above:
1.01
2.02
3.03
4.04
5.05
6.06
7.070001
8.080001
9.090001
10.1
You can see that after just 7 addition..already rounding is occurring.
One of the first lessons in computing science is that computers do NOT accurately store floating point numbers (they are only approximate). And thus one REALLY needs to avoid using real numbers when working on financial applications that involve money. Note that the above code runs the SAME even in Excel.
The lesson here is that you thus when using applications that involve money, you need to use integer values to avoid rounding. Currency is such a data type (it is an integer value scaled to include decimal places).
I have a article here that thus explains how to handle numbers that don't cause rounding errors in Access:
http://www.kallal.ca/Articles/rounding/Rounding.html
The short story and rule is simply use currency data types, since floating numbers will cause you many problems.

Decimal or Double when storing rounded currency values in an Access database?

I am currently importing a data set that includes currency values into an Access database. Although I've read that I should be using the decimal data type for currency, can I not use double to cut down on the file size if the values are rounded to the nearest dollar?
As far as I can tell, the issue with using double for currency is due to rounding, but I won't be doing calculations on the data directly. Any calculations will be done by the application/user.
Similarly, as the data is fixed-length, some of the decimal values are represented by whole numbers. For example, some fields may contain a value of 12345, but the actual value is 12.345. This requires that I import the data and then update the values; dividing by 1000 in the example above.
Will using double in this fashion cause rounding errors as well?
Yes, divisions can and will introduce rounding errors.
You want to use "currency" for ANY kind of business software. In fact if you don't have a currency data type then you use SCALED integers (you scale the results). You thus store
$123.52
As
1235200
(Assuming 4 decimal places)
The reason of course is "real" numbers in computers are only a representation and are only approximate – they are subject to rounding.
This is SIMPLE code:
Public Sub TestAdd()
Dim MyNumber As Single
Dim i As Integer
For i = 1 To 10
MyNumber = MyNumber + 1.01
Debug.Print MyNumber
Next i
End Sub
Here is the actual output of the above:
1.01
2.02
3.03
4.04
5.05
6.06
7.070001
8.080001
9.090001
10.1
Imagine the above – after just 7 SIMPLE and SILLY additions we already getting WRONG answers. And VBA even in Excel will do the SAME. So as noted, we are using 0.01, but it only approximate! (so while we assume this value is 1/100th, it only approximate when using the "real" format in computers.
So computers cannot and do NOT store real numbers to an exact precision. You get rounding errors as a result.
For payroll or anything to do with business applications and money you have to use scaled integers else your tables and accounting and even reports will NOT add up and you experience rounding errors.
I cannot think of any benefits in terms of storage space unless you storing many millions of rows of data. MUCH worse is if you export this data to some other system, then exporting "real" numbers can introduce all kinds of artifacts and even exponents when exporting - use currency - you be safe in what you see and have.

Best data type to store money values in MySQL

I want to store many records in a MySQL database. All of them contains money values. But I don't know how many digits will be inserted for each one.
Which data type do I have to use for this purpose?
VARCHAR or INT (or other numeric data types)?
Since money needs an exact representation don't use data types that are only approximate like float. You can use a fixed-point numeric data type for that like
decimal(15,2)
15 is the precision (total length of value including decimal places)
2 is the number of digits after decimal point
See MySQL Numeric Types:
These types are used when it is important to preserve exact precision, for example with monetary data.
You can use DECIMAL or NUMERIC both are same
The DECIMAL and NUMERIC types store exact numeric data values. These types are used when it is important to preserve exact precision, for example with monetary data. In MySQL, NUMERIC is implemented as DECIMAL, so the following remarks about DECIMAL apply equally to NUMERIC. : MySQL
i.e. DECIMAL(10,2)
Good read
I prefer to use BIGINT, and store the values in by multiply with 100, so that it will become integer.
For e.g., to represent a currency value of 93.49, the value shall be stored as 9349, while displaying the value we can divide by 100 and display. This will occupy less storage space.
Caution:
Mostly we don't perform currency * currency multiplication, in case if we are doing it then divide the result with 100 and store, so that it returns to proper precision.
It depends on your need.
Using DECIMAL(10,2) usually is enough but if you need a little bit more precise values you can set DECIMAL(10,4).
If you work with big values replace 10 with 19.
If your application needs to handle money values up to a trillion then this should work: 13,2
If you need to comply with GAAP (Generally Accepted Accounting Principles) then use: 13,4
Usually you should sum your money values at 13,4 before rounding of the output to 13,2.
At the time this question was asked nobody thought about Bitcoin price. In the case of BTC, it is probably insufficient to use DECIMAL(15,2). If the Bitcoin will rise to $100,000 or more, we will need at least DECIMAL(18,9) to support cryptocurrencies in our apps.
DECIMAL(18,9) takes 12 bytes of space in MySQL (4 bytes per 9 digits).
We use double.
*gasp*
Why?
Because it can represent any 15 digit number with no constraints on where the decimal point is. All for a measly 8 bytes!
So it can represent:
0.123456789012345
123456789012345.0
...and anything in between.
This is useful because we're dealing with global currencies, and double can store the various numbers of decimal places we'll likely encounter.
A single double field can represent 999,999,999,999,999s in Japanese yens, 9,999,999,999,999.99s in US dollars and even 9,999,999.99999999s in bitcoins
If you try doing the same with decimal, you need decimal(30, 15) which costs 14 bytes.
Caveats
Of course, using double isn't without caveats.
However, it's not loss of accuracy as some tend to point out. Even though double itself may not be internally exact to the base 10 system, we can make it exact by rounding the value we pull from the database to its significant decimal places. If needed that is. (e.g. If it's going to be outputted, and base 10 representation is required.)
The caveats are, any time we perform arithmetic with it, we need to normalize the result (by rounding it to its significant decimal places) before:
Performing comparisons on it.
Writing it back to the database.
Another kind of caveat is, unlike decimal(m, d) where the database will prevent programs from inserting a number with more than m digits, no such validations exists with double. A program could insert a user inputted value of 20 digits and it'll end up being silently recorded as an inaccurate amount.
If GAAP Compliance is required or you need 4 decimal places:
DECIMAL(13, 4)
Which supports a max value of:
$999,999,999.9999
Otherwise, if 2 decimal places is enough:
DECIMAL(13,2)
src: https://rietta.com/blog/best-data-types-for-currencymoney-in/
Indeed this relies on the programmer's preferences. I personally use: numeric(15,4) to conform to the Generally Accepted Accounting Principles (GAAP).
Try using
Decimal(19,4)
this usually works with every other DB as well
Storing money as BIGINT multiplied by 100 or more with the reason to use less storage space makes no sense in all "normal" situations.
To stay aligned with GAAP it is sufficient to store currencies in DECIMAL(13,4)
MySQL manual reads that it needs 4 bytes per 9 digits to store DECIMAL.
https://dev.mysql.com/doc/refman/8.0/en/precision-math-decimal-characteristics.html
DECIMAL(13,4) represents 9 digits + 4 fraction digits (decimal places) => 4 + 2 bytes = 6 bytes
compare to 8 bytes required to store BIGINT.
There are 2 valid options:
use integer amount of currency minor units (e.g. cents)
represent amount as decimal value of the currency
In both cases you should use decimal data type to have enough significant digits. The difference can be in precision:
even for integer amount of minor units it's better to have extra precisions for accumulators (account for accumulating 10% fees from 1-cent operations)
different currencies have different number of decimals, cryptocurrencies have up to 18 decimals
The number of decimals can change over time due to inflation
Source and more caveats and facts.
Multiplies 10000 and stores as BIGINT, like "Currency" in Visual Basic and Office. See https://msdn.microsoft.com/en-us/library/office/gg264338.aspx