How to create an uint256 in PostgreSQL - postgresql

How can I create an uint256 data type in Postgres? It looks like they only support up to 8 bytes for integers natively..
They offer decimal and numeric types with user-specified precision. For my app, the values are money, so I would assume I would use numeric over decimal, or does that not matter?
NUMERIC(precision, scale)
So would I use NUMERIC(78, 0)? (2^256 is 78 digits) Or do I need to do NUMERIC(155, 0) and force it to always be >= 0 (2^512, 155 digits, with the extra bit representing the sign)? OR should I be using decimal?

numeric(78,0) has a max value of 9.999... * 10^77 > 2^256 so that is sufficient.

You can create a domain.
CREATE DOMAIN uint_256 AS NUMERIC NOT NULL
CHECK (VALUE >= 0 AND VALUE < 2^256)
CHECK (SCALE(VALUE) = 0)
This creates a reusable uint_256 datatype which is constrained to be within the 2^256 limit and also prevents rounding errors by only allowing the scale of the number to be 0 (i.e. throws an error with decimal values). There is nothing like NULL in Solidity so the datatype should not be nullable.
Try it: dbfiddle

Related

storing decimal into pgtype numeric

I was working with pgtype.NumRange. The lower and upper bounds are typed pgtype.Numeric. pgtype.Numeric has the following fields
type Numeric struct {
Int *big.Int
Exp int32
Status Status
NaN bool
InfinityModifier InfinityModifier
}
I guess I'm suppose to able to represent any number using the duo of the Int and Exp fields, but I don't know how to, as big.Int and `int32' are integer types.
From Postgres docs, I can see that numrange can take decimal values in any of lower and upper bounds and data type numeric is a superset of decimal type. So I know I should be able to use decimals, but
how can I go about this?

DB2 : Length of concatenated fields different

Below query gives 2 different wrong length but same numbers ,In IBM db2 SQL
Why there is 2 different length for same value ?
select
decimal(TRIM(cast(15 as char(2)))||TRIM(LPAD(cast(7 as char(2)),2,'0'))||TRIM(LPAD(cast(13 as char(2)),2,'0'))),
length(decimal(TRIM(cast(15 as char(2)))||TRIM(LPAD(cast(7 as char(2)),2,'0'))||TRIM(LPAD(cast(13 as char(2)),2,'0')))),
decimal(TRIM(substr(replace(char(current_date -1 days,ISO),'-',''),3,6)),6,0),
length(decimal(TRIM(substr(replace(char(current_date -1 days,ISO),'-',''),3,6)),6,0))
from sysibm.sysdummy1
These numbers are not the same value the first one is 15713 and the second is 150713.
DECIMAL(x,p,s) returns a packed decimal value of precision p, scale s.
A packed decimal(p,s) only takes p/2 + 1 bytes of memory.
So 6 /2 + 1 = 4, which is the value LENGTH() returns for packed decimal expressions per the (DB2 for IBM i) manual

How do you put multiple values into one variable or field without using a list and then parsing?

Sometimes there is a need to have multiple values in one variable or database field, even though that violates relational normalization principles. In python and other languages that support lists, that's easy. In others it is not. See insert multiple values in single attribute
One common technique is to concatenate values into a comma delimited string: "1,2,3" or "English,French,Spanish" and then extracting values by parsing.
When the valid values come from an enumerated list, is there another way that does not require parsing?
Yes. Use prime numbers, multiply them together, then factor them out.
The field type to use is integer or large integer
Use code values that are prime numbers
3 == English
5 == French
7 == Spanish
11 == Italian
Store the product of all that apply into the field.
21 == English and Spanish
385 == French, Spanish and Italian
Use modulo functions to determine which values are in the field
if ( field % 3 == 0 ) { english() ;}
if ! (field % 5) { french() ;}
=IF(NOT(MOD(A203,5)),"French","")
The same value can appear multiple times
9 == English, English
I first used this technique to store dimensions.
3 == time
5 == length
7 == mass
11 == charge
13 == temperature
17 == moles
For example, a "first moment" lever-arm would have a dimension value of 35 == mass * length.
To store fractional dimensions in an integer, I multiplied fractional dimensions by the product of all of them and dealt with it in processing.
255255 == 3*5*7*11*13*17
force == mass * length / (second^2)
force == ( 7 * 5 / ( 3 * 3 ) ) * 255255 * 255255
force == 253381002875
The reason I used integers was to avoid dealing with invalid equality comparisons due to rounding errors.
Please do not ask for the code to extract the fractional dimensions. All this was 40 years ago in APL/360.
If you don't need to allow for multiples of the same value, then you could use a bit map. Depending on whether there are up to 8, 16, 32, 64, or 128 allowed values, they could fit in a 1, 2, 4, 8, or 16 byte integer.

arc4random throwing out huge numbers

In a cocos2d game, I use arc4random to generate random numbers like this:
float x = (arc4random()%10 - 5)*delta;
(delta is the time between updates in the scheduled update method)
NSLog(#"x: %f", x);
I have been checking them like that.
Most of the numbers that I get are like this:
2012-12-29 15:37:18.206 Jumpy[1924:907] x: 0.033444
or
2012-12-29 15:37:18.247 Jumpy[1924:907] x: 0.033369
But for some reason I get numbers like this sometimes:
2012-12-29 15:37:18.244 Jumpy[1924:907] x: 71658664.000000
Edit: Delta is almost always:
2012-12-29 17:01:26.612 Jumpy[2059:907] delta: 0.016590
I thought it should return numbers in a range of -5 to 5 (multiplied by some small number). Why I am getting numbers like this?
arc4random returns a u_int32_t. The u_ part tells you that it's unsigned. So all of the operators inside the parentheses use unsigned arithmetic.
If you perform the subtraction 2 - 5 using unsigned 32-bit arithmetic, you get 232 + 2 - 5 = 232 - 3 = 4294967293 (a “huge number”).
Cast to a signed type before performing the subtraction. Also, prefer arc4random_uniform if your deployment target is iOS 4.3 or later:
float x = ((int)arc4random_uniform(10) - 5) * delta;
If you want the range to include -5 and 5, you need to use 11 instead of 10, because the range [-5,5] (inclusive) contains 11 elements:
float x = ((int)arc4random_uniform(11) - 5) * delta;
arc4random returns a u_int32_t, an unsigned type. The modulus is also performed using unsigned arithmetic, which yields a number between 0 and 9, as expected (by the way, don't ever do this; use arc4random_uniform instead). You then subtract 5, which is interpreted as an unsigned value, yielding a possibly huge positive value due to underflow.
The solution is to explicitly type the 5 by storing it in a variable of signed type or with a suffix (like 5L).
Looks like arc4random % 10 becomes less than 5, and you are working with negative integer later.
What is the value of delta?

Regarding BigDecimal

I have a csv file where amount and quantity fields are present in each detail record except header and trailer record. Trailer record has a total charge values which is the total sum of quantity multiplied by amount field in detail records . I need to check whether the trailer total charge value is equal to my calculated value of amount and quantity fields. I am using the double data type for all these calculations. When i browsed i am able to understand from the below web link that it might create an issue using double datatype while comparison with decimal points. It's suggesting to using BigDecimal
http://epramono.blogspot.com/2005/01/double-vs-bigdecimal.html
Will i get issues if i use double data type. How can i do the calculations using BigDecimal. Also i am not sure how many digits i will get after decimal points in csv file. Also amount can have a positive or negative value.
In csv file
H,ABC.....
"D",....,"1","12.23"
"D",.....,"3","-13.334"
"D",......,"2","12"
T,csd,123,12.345
------------------------------ While Validation i am having the below code --------------------
double detChargeCount =0;
//From csv file i am reading trailer records charge value
String totChargeValue = items[3].replaceAll("\"","").trim();
if (null != totChargeValue && !totChargeValue.equals("")) {
detChargeCount = new Double(totChargeValue).doubleValue();
if(detChargeCount==calChargeCount)
validflag=true;
-----------------------While reading CSV File i am having the below code
if (null != chargeQuan && !chargeQuan.equals("")) {
tmpChargeQuan=Long(chargeQuan).longValue();
}
if (null != chargeAmount && !chargeAmount.equals("")) {
tmpChargeAmt=new Double(chargeAmount).doubleValue();
calChargeCount=calChargeCount+(tmpChargeQuan*tmpChargeAmt);
}
I had declared the variables tmpChargeQuan, tmpChargeAmt, calChargeCount as double
Especially for anything with financial data, but in general for everything dealing with human readable numbers, BigDecimal is what you want to use instead of double, just as that source says.
The documentation on BigDecimal is pretty straight-forward, and should provide everything you need.
It has a int, double, and string constructors, so you can simply have:
BigDecimal detChargeCount = new BigDecimal(0);
...
detChargeCount = new BigDecimal(totChargeValue);
The operators are implemented as functions, so you'd have to do things like
tmpChargeQuan.multiply(tmpChargeAmt)
instead of simply tmpChargeQun * tmpChargeAmt, but that shouldn't be a big deal.
but they're all defined with all the overloads you could need as well.
It is very possible that you will have issues with doubles, by which I mean the precomputed value and the newly computed value may differ by .000001 or less.
If you don't know how the value you are comparing to was computed, I think the best solution is to define "equal" as having a difference of less than epsilon, where epsilon is a very small number such as .0001.
I.e. rather than using the test A == B, use abs(A - B) < .0001.