Best collection to use with Double as key
I have this object:
Public Cactus{
Public Double key;
Public String value;
}
I have about ~ 100 Cactus
which have a unique key and a value that has some duplicates. However, I will need to get the value for the key by about 2000 times. My values Key
range from -10 to 280.
I want this process to be as fast as possible. What would be the best approach to do this? I thought using HashTable
, although I have always used one with Integer
, not Double
, and for some reason I am concerned that it is not recommended to use Double
both Key
.
Given my scenario, which collection would be the best to use?
source to share
Using a double as a key in a dictionary is usually a very bad idea. You will run into all of the presentation errors where you think you have stored 0.1 in the dictionary, but in fact you have stored something very close but not quite equal to 0.1.
I would suggest using a different type (string?) If you need exact matches.
If you don't want exact matches, but just find the closest value, consider something like SortedList instead.
source to share
Yes, using a double value as a key seems awkward. Are these double values ββthe result of some computation that may have some very small round-off errors ? If you are going to calculate these values ββand access the collection using these calculated values, it is very likely that there will be unwanted results.
For example, you store an item with a key of 1.01. Your calculations will result in 1.010000000000000123 and will not match the stored key.
If it is not, I see no problem using a double value as a key in a dictionary or hash table collection.
BTW using a typed dictionary (i.e. Dictionary<double, string>
) will be easier to use than HashTable
.
source to share
I agree with @Mark Byers and @tafa that using a double key directly is a bad idea. If you want to make sure you have exactly the same number, you can create a string key based on the bytes that make up the double. The following structure maps a double value to the same memory space of 8 bytes, so no custom conversion is required.
[StructLayout(LayoutKind.Explicit)]
public struct TestStruct
{
[FieldOffset(0)]
public byte byte1;
[FieldOffset(1)]
public byte byte2;
[FieldOffset(2)]
public byte byte3;
[FieldOffset(3)]
public byte byte4;
[FieldOffset(4)]
public byte byte5;
[FieldOffset(5)]
public byte byte6;
[FieldOffset(6)]
public byte byte7;
[FieldOffset(7)]
public byte byte8;
[FieldOffset(0)]
public double double1;
}
It can then be wrapped in a function like this (assuming you have a struct defined in your class as a private variable)
static string GetStringKey(double key)
{
_conversionStruct.double1 = Double.MaxValue;
return String.Format("{0}:{1}:{2}:{3}:{4}:{5}:{6}:{7}",
_conversionStruct.byte1,
_conversionStruct.byte2,
_conversionStruct.byte3,
_conversionStruct.byte4,
_conversionStruct.byte5,
_conversionStruct.byte6,
_conversionStruct.byte7,
_conversionStruct.byte8);
}
And it is used like this.
var s1 = GetStringKey(double.MaxValue);
var s2 = GetStringKey(double.MinValue);
which gives ...
s1="255:255:255:255:255:255:239:127"
s2="255:255:255:255:255:255:239:255"
source to share