Enums with positive and negative values - c#

I need to create a large enum which will be used as bit flags. Using the standard doubling i.e. 1, 2, 4 to ensure uniqueness of any combination is fine except that I run out of numbers if I use the int (2 billion upperlimit). I also cannot use a big int as Sql server has a limitation on bitwise operations and will truncate to 10 characters.
What I wanted to know is how to throw negative numbers in there as well and still ensure that all combinations remain unique. (for example some the enum values used in the ADO.NET library seem to have negative integers).

You can create an enum based on a ulong :
[Flags]
enum Foo : ulong
{
A = 1 ,
B = 2 ,
C = 4 ,
. . .
}
Store that in your database as two integers, something like this:
Save( Foo value )
{
ulong bitfield = (ulong) value ;
int hiNibble = (int)( (bitfield>>32) & 0x00000000FFFFFFFF ) ;
int loNibble = (int)( (bitfield>>0) & 0x00000000FFFFFFFF ) ;
// store the hi and lo nibbles as two integer columns in your database
}
In your database, create the table as something like
create table dbo.some_table
(
hiNibble int ,
loNibble int ,
bitField as convert(bigint, convert(varbinary,hiNibble) + convert(varbinary,loNibble) )
)
Now you have two 32-bit integers you can bit twiddle in SQL and you've got a 64-bit integer you can pass back to your C# code and rehydrate as the ulong-based enum it represents.

Related

How to (theoretically) print all possible double precision numbers in C#?

For a little personal research project I want to generate a string list of all possible values a double precision floating point number can have.
I've found the "r" formatting option, which guarantees that the string can be parsed back into the exact same bit representation:
string s = myDouble.ToString("r");
But how to generate all possible bit combinations? Preferably ordered by value.
Maybe using the unchecked keyword somehow?
unchecked
{
//for all long values
myDouble[i] = myLong++;
}
Disclaimer: It's more a theoretical question, I am not going to read all the numbers... :)
using unsafe code:
ulong i = 0; //long is 64 bit, like double
unsafe
{
double* d = (double*)&i;
for(;i<ulong.MaxValue;i++)
Console.WriteLine(*d);
}
You can start with all possible values 0 <= x < 1. You can create those by having zero for exponent and use different values for the mantissa.
The mantissa is stored in 52 bits of the 64 bits that make a double precision number, so that makes for 2 ^ 52 = 4503599627370496 different numbers between 0 and 1.
From the description of the decimal format you can figure out how the bit pattern (eight bytes) should be for those numbers, then you can use the BitConverter.ToDouble method to do the conversion.
Then you can set the first bit to make the negative version of all those numbers.
All those numbers are unique, beyond that you will start getting duplicate values because there are several ways to express the same value when the exponent is non-zero. For each new non-zero exponent you would get the value that were not possible to express with the previously used expontents.
The values between 0 and 1 will however keep you busy for the forseeable future, so you can just start with those.
This should be doable in safe code: Create a bit string. Convert that to a double. Output. Increment. Repeat.... A LOT.
string bstr = "01010101010101010101010101010101"; // this is 32 instead of 64, adjust as needed
long v = 0;
for (int i = bstr.Length - 1; i >= 0; i--) v = (v << 1) + (bstr[i] - '0');
double d = BitConverter.ToDouble(BitConverter.GetBytes(v), 0);
// increment bstr and loop

generate seemingly random unique numeric ID in SQL Server

I need to use SQL Server to generate seemingly random unique 8-digit numeric ID (can pad zeros at front). Is there a built-in functionality for this? I saw this Identity property, but it is sequential, not random.
If this is not possible, is it good practice to directly write a randomly generated ID to db then check for exception? (note that my app is multi-threaded, so checking before writing doesn't guarantee uniqueness unless done in atomic action.)
Thanks!
UPDATE: Added "numeric" to clarify.
Edited to show that the randomness doesn't need to be cryptographically strong or anything near. Just seemingly random is good enough. Oliver suggested an elegant solution, and I've posted an answer using that approach. Thanks, Oliver!
Randomness clashes with uniqueness, but there is an elegant solution suggested by #Oliver when the numbers only need to appear random, while an underlying order exists. From Erics' http://ericlippert.com/2013/11/14/a-practical-use-of-multiplicative-inverses/, the main idea is that for given a pair of coprime, positive integers x and m, we can find a multiplicative inverse y where (x*y) % m == 1. This is very useful because given a database row ID z, we can map z to another integer by doing encoded = (z*x) % m. Now given this encoded, how can we get z back? Simple, z = (encoded * y) % m since (x*y*z) % m == z given z < m. This one-to-one correspondence guarantees uniqueness of the "encoded" while provides an apparance of randomness.
Note that Eric showed how to calculate this multiplicative inverse. But if you are lazy, there is this.
In my implementation, I just store the sequential ID of each row as it is. Then, each ID is mapped to another number, something simlar to the "InvoiceNumber" in the article. When the customer hands you back this "InvoiceNumber", you can map it back to its original database ID by using multiplicative inverse.
Below is a C# example of encoding and decoding sequence from 0 to 9.
public static void SeeminglyRandomSequence()
{ //use long to prevent overflow
long m = 10; //modulo, choose m to be much larger than number of rows
long x = 7; //anything coprime to m
long y = 3; //multiplicative inverse of x, where (y*x) % m == 1
List<long> encodedSequence = new List<long>();
List<long> decodedSequence = new List<long>();
for (long i = 0; i < m; i++)
{
long encoded = (i * x) % m;
encodedSequence.Add(encoded);
}
foreach (long encoded in encodedSequence)
{
long decoded = (encoded * y) % m;
decodedSequence.Add(decoded);
}
Debug.WriteLine("just encoded sequence from 0 to {0}. Result shown below:", (m - 1));
Debug.WriteLine("encoded sequence: " + string.Join(" ", encodedSequence));
Debug.WriteLine("decoded sequence: " + string.Join(" ", decodedSequence));
}
The printed result is:
just encoded sequence from 0 to 9. Result shown below:
encoded sequence: 0 7 4 1 8 5 2 9 6 3
decoded sequence: 0 1 2 3 4 5 6 7 8 9
As you can see, each input is mapped to a unique output, and it's easy to reverse this mapping. In your application, you might want to start with 1 since 0 always maps to itself.
Just to show the "apparent randomness" for larger m, below are the first 10 mappings when m=100,000,000:
just encoded sequence from 1 to 10. Result shown below:
encoded sequence: 81654327 63308654 44962981 26617308 8271635 89925962 71580289 53234616 34888943 16543270
decoded sequence: 1 2 3 4 5 6 7 8 9 10
USE the below query to create 8 digit randow unique number.
SELECT CAST(RAND() * 100000000 AS INT) AS [RandomNumber]
To avoid exception while inserting of existing number into DB use below query.
IF NOT EXIST(SELECT UniqueColumnID FROM TABLENAME WHERE UniqueColumnID = #RandowNumber)
BEGIN
--Insert query using #RandowNumber.
END
you can use NEWID() to generate uniqueIdentifier data which always random and unique each time
To get 8 character you can use substring, left etc function.
select substring( cast( NEWID() as varchar(100)),0,8)
or new logic for uniqueness:- http://forums.asp.net/t/1474299.aspx?How+to+generate+unique+key+of+fixed+length+20+digit+in+sql+server+2005+
select Left(NewID(),4)+Right(NewId(),4)
you can use random() function for this too.
check this links:
How do I generate random number for each row in a TSQL Select?
How to get numeric random uniqueid in SQL Server
Updated
If you want to unique value int data-type and 8 character long. Good to make a identity column like below, which is good for 8 character length data means (10,000,000). But after that it gives you exception. So be carefull which logic you want.(Still I say, its bad idea). store as random value as above with more length so uniqueness comes.
create table temp (id numeric(8,0) IDENTITY(1,1) NOT NULL, value1 varchar ) --if you want do not stop after 8 character , give int datatype.
insert into temp values( 'a'), ('b'), ('c')
select * from temp
drop table temp
Finally
It's not guaranteed unique but it's hard to get duplicates with NEWID()(refer above link forums.asp.net)
Create a SQL function or procedure as follow:
ALTER FUNCTION [dbo].[GenerateRandomNo]
(
#Lower INT = 111111111,
#Upper INT = 999999999
)
RETURNS NVARCHAR(128)
AS
BEGIN
DECLARE #TempRandom FLOAT
DECLARE #Random NVARCHAR(128);
-- Add the T-SQL statements to compute the return value here
SELECT #TempRandom = RandomNo from RandomNo
SELECT #Random = CONVERT(NVARCHAR(128),CONVERT(INT,ROUND(((#Upper - #Lower -1) * #TempRandom + #Lower), 0)))
WHILE EXISTS(SELECT * FROM Table WHERE Column = #Random)
BEGIN
SELECT #TempRandom = RandomNo from RandomNo
SELECT #Random = CONVERT(NVARCHAR(128),CONVERT(INT, ROUND(((#Upper - #Lower -1) * #TempRandom + #Lower), 0)))
END
-- Return the result of the function
RETURN #Random
END
And then call that function passing parameter if you want to generate random no with specific length or range.
--create
-- table Tbl( idx int)
DECLARE
#unique_id int
SET #unique_id= ( SELECT ROUND( 89999999 * RAND(
) + 10000000 , 0
)
)
IF not EXISTS( SELECT idx
FROM tbl
WHERE idx = #unique_id
)
BEGIN
INSERT INTO tbl( idx
)
VALUES( #unique_id
)
SELECT #unique_id, * FROM tbl
END;
--TRUNCATE TABLE tbl

Convert 24 bit value to float and back

It is possible to convert 24 bit integer value into float and then back to 24 bit integer without losing data?
For example, let's consider 8 bit int, a byte, range is [-127..127] (we drop -128).
public static float ToFloatSample (byte x) { return x / 127f; }
So, if x == -127, result will be -1, if x == 127, result will be 1. If x == 64, result will be ~0.5
public static int ToIntSample (float x) { return (int) (x * 127f); }
So now:
int x = some_number;
float f = ToFloatSample (x);
int y = ToIntSample (f);
Will always x == y ? Using 8 bit int yes, but what if I use 24 bit?
Having thought about your question, I now understand what you're asking.
I understand you have 24-bits which represent a real number n such that -1 <= n <= +1 and you want to load this into an instance of System.Single, and back again.
In C/C++ this is actually quite easy with the frexp and ldexp functions, documented here ( how can I extract the mantissa of a double ), but in .NET it's a more involved process.
The C# language specification (and thusly, .NET) states it uses IEEE-754 1989 format, which means you'll need to dump the bits into an integer type so you can perform the bitwise logic to extract the components. This question has already been asked here on SO except for System.Double instead of System.Single, but converting the answer to work with Single is a trivial exercise for the reader ( extracting mantissa and exponent from double in c# ).
In your case, you'd want to store your 24-bit mantissa value in the low-24 bits of an Int32 and then use the code in that linked question to load and extract it from a Single instance.
Every integer in the range [-16777216, 16777216] is exactly representable as an IEEE 754 32-bit binary floating point number. That includes both the unsigned and 2's complement 24 bit integer ranges. Simple casting will do the job.
The range is wider than you would expect because there is an extra significand bit that is not stored - it is a binary digit that is known not to be zero.

Mapping an integer bit mask

I have an integer input representing a 32 bit mask.
This mask goes alongside a string array of length 32.
Sometimes the string array will contain nulls or empty strings. In these situations I would like to "remove" the null-or-empty-string bit from from the mask.
This mapping would involve shifting all subsequent bits to the right:
"d" "c" null "a" -> "d" "c" "a"
1 1 1 1 -> 0 1 1 1
Finally, I would like to be able to unmap this mask when I'm finished with it. In this case I would be inserting zeroes wherever a null-or-empty-string exists in the string array.
The string array does not change between these mappings, so I am not concerned about the data becoming desynchronised.
Without using LINQ or lambda expressions, how can I implement these methods?
private static readonly string[] m_Names;
public static int MapToNames(int mask)
{
}
public static int MapFromNames(int mask)
{
}
I have been looking a little at the BitArray class, but it doesn't seem very helpful as it doesn't provide methods for converting to/from an integer.
I know that this is not the answer of your question, but think about saving bit mask values in integer field like a sum of all bit mask fields. It is easy to control and maintain. How to check for the bit mask values.
if(bitmaskIntValue & value)
{
}
Example: You have bitmaskIntValue = 10-> 2^1 + 2^3
if(bitmaskIntValue & 2)
{
//first or second input is checked.(depending from where you start 2^0 or 2^1)
}

How can I save space when storing boolean data in c#

I need to store boolean data in Windows Azure. I want to make the space these take up as small as possible. What I have is about fifteen fields with values that are true of false.
field_1 = true;
field_2 = true;
field_a = false;
field_xx = true;
I had an idea that I could take these, convert the true and false to 1s and 0s and then store as a string something like 1101. Is there a simple way that I could do this coding and then uncode when getting the data out? Note that the field names are all different and so I can't use a fancy for loop to go through field names.
int bits = (field_1 ? 1 : 0) | (field_2 ? 2 : 0) | (field_3 ? 4 : 0) | (field_4 ? 8 : 0) | ...
field_1 = (bits & 1) != 0;
field_2 = (bits & 2) != 0;
field_3 = (bits & 4) != 0;
field_4 = (bits & 8) != 0;
...
I don't think you can even imagine how skeptical I am that this will help in any way, shape or form. 15 booleans is literally nothing.
Now, if you insist on going down this path, the best way would be to store them as a single int and use & to read them out and | to write them back in.
You can use a BitArray to pack the booleans into an int:
BitArray b = new BitArray(new bool[] { field_1, field_2, ..., field_xy });
int[] buffer = new int[1];
b.CopyTo(buffer, 0);
int data = buffer[0];
You can use a byte or int array. A byte can hold up to 8 booleans, an int up to 32. To hold up to 16 booleans you could use a byte array with two bytes, or a single int, depending on whether the overhead of an array or the unused bits in the int take up more space. You could also use the BitConverter class to convert a two byte array into a short.
To get the booleans back you create a BitArray from an array of byte or int:
BitArray b = new BitArray(new int[] { data });
field_1 = b[0];
field_2 = b[1];
...
field_xy = b[14];
Consider an enumeration with the [Flags] attribute
[Flags]
public enum Values
{
Field1 = 1,
Field2 = 2,
Field3 = 4,
Field4 = 8
}
Values obj = Field1 | Field2;
obj.HasValue(Field1); //true
obj.HasValue(Field3); //false
int storage = (int)obj;// 3
Don't bother. You're using boolean values, which are already about as small (for an individual value) as you can get (1 byte I believe). And the small amount of space that you might be able to save would not be worth the added complexity of your code, plus the time it would take you to develop it.
A few more thoughts: think how you'd use such a construct. Currently, if you look at field_1 and see a value of true, you don't have to look further into the implementation to figure out the actual value. However, let's say you had the following string: "100101011011010" (or an integer value of 19162, which would be more efficient). Is field_1 true, or is it false? It's not inherently obvious -- you need to go find the implementation. And what happens when you need to support more fields somewhere down the line? You'll save yourself a lot of heartache by sticking with what you've got.
Storing these as characters will take either 8 or 16 bits per value. I'd pack them into the an array of the longest unsigned integer available, using bit-shifting operations.
There is a great post on this at:
http://blog.millermedeiros.com/2010/12/using-integers-to-store-multiple-boolean-values/
You could do this with an int and using xor http://www.dotnetperls.com/xor
I saw a project that did this about 15 years ago. But it ended up with a limitation of 32 roles in the system (it used a 32 bit number). That product does not exist today :)
So do not do it, store values in an array or seperate fields.
you could use Enum with the flags attribute. You say you have 15 fields. So you could try using something like
[Flags]
enum Fieldvals
{
Field1, Field2, ....
}
take a look at http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx for the guidelines
Check out the BitArray class, it should do exactly what you need.
Example:
BitArray bits = new BitArray
(
new bool[]
{
false, true, false, false, true,
false, true, false, true, false,
false, true, false, true, false
}
);
short values = 0;
for( int index = 0; index < bits.Length; index++ )
{
if( bits[ index ] )
values |= ( short )( values | ( 1 << index ) );
}
Console.WriteLine( Convert.ToString( values, 2 ) );
You now have 15 bool variables stored in a single 16 bit field.
You can store your flags in an integer value. Here are some helper methods to accomplish that:
// Sets the given bit position in the UInt32 to the specified boolean value
public static UInt32 Set(UInt32 u, int position, bool newBitValue)
{
UInt32 mask = (UInt32)(1 << position);
if (newBitValue)
return (u | mask)
else
return (u & ~mask);
}
// Gets a bit value from the supplied UInt32
public static bool Get(UInt32 u, int position)
{
return ((u & (UInt32)(1 << position)) != 0);
}

Categories

Resources