2

I have this object:

Public Cactus{
    Public Double key;
    Public String value;
}

I have about ~100 Cactus, which all have a unique key, and a value that has some duplicates. I will however have to retrieve the value for a key about ~2000 times. My Key values varies between -10 and 280.

I want this process to be as quick as possible. What would be the best approach for this? I was thinking using a HashTable, although I always used one with Integer and not Double, and for some reason I am worried that it's not good practice to use Double as Key.

Given my scenario, which collection would be the best to use?

Alexandre
  • 4,382
  • 2
  • 23
  • 33
  • Convert your doubles into strings and make them as keys, I guess this is more feasible and profitable :D – Mackintoast Feb 10 '12 at 15:47
  • why can't you use a `UInt64` as a key (presuming that the key has to be 64-bits long) ? – Djole Feb 10 '12 at 15:53
  • The object in question is based off "real world" object, and pretty it is pretty much used throughout the application. I can't exactly "hack" myself an ID without having to refactor everything that's been done in the last 10 years. Hopefully I didn't misunderstand the intent of the `UInt64`! – Alexandre Feb 10 '12 at 15:59

4 Answers4

11

Using a double as a key in a dictionary is generally a really bad idea. You will run into all sorts of problems with representation errors where you think you stored 0.1 in the dictionary but actually you stored something very close to but not quite equal to 0.1.

I'd suggest using another type (string?) if you need exact matches.

If you don't want exact matches but just finding the closest value, consider something like a SortedList instead.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • I'm afraid this is not possible, I've looked at better ways to have a unique identifier for my `Cactus and this is pretty much all I've got... Oh The Joy! – Alexandre Feb 10 '12 at 15:48
  • 1
    You don't need to get rid of the existing double identifier to do this. Have they key be a string (some representation of the double truncated/rounded/whatever) and the value be your Cactus object so that the real (double) key is still held onto. – Servy Feb 10 '12 at 16:32
2

I agree with @Mark Byers and @tafa that using the double as the key directly is a bad idea. If you want to make sure that you have exactly the same number you could build a string key based on the bytes that make up the double. The following struct maps a double to the same memory space as 8 bytes so that no custom conversion is needed.

[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 wrapped in a function like this (assuming that you have the 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 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"
Shipps
  • 76
  • 1
  • 6
2

Yes, using a double value as a key seems awkward. Are those double values results of some computations that may have some very tiny round-off errors? If you are going to compute those values and access the collection with those computed values, it is highly likely that there is going to be unwanted results.

For example, you store an element with key value 1.01. Your computations would result 1.010000000000000123, and will not match the stored key.

If this is not the case, then I see no problem using a double value as the key of a dictionary, or hashtable collection.

BTW, using a typed Dictionary (i.e., Dictionary<double, string>) will be easier to use than a HashTable.

tafa
  • 7,146
  • 3
  • 36
  • 40
0
  • If you can, make the double a long, and use that as key. (multiply by multiple of 10 to get rid of the decimal point)
  • Another option, which is not as good as the first, is to convert the double to string.
Adrian
  • 5,603
  • 8
  • 53
  • 85