2010-10-24 2 views
2

У меня есть проект приложения, который выполняется как управляемым, так и неуправляемым кодом, и мне нужно использовать тот же алгоритм для хэширования двойных значений в обеих системах. поэтому либо я переопределю System.Double.GetHashCode(), либо воспользуюсь его алгоритмом в коде C++. Я не мог найти алгоритм double.gethashcode и решил переопределить функцию. но я получил странную ошибку.Double.GetHashCode алгоритм или переопределение

Не может неявно преобразовать тип двойной в System.Double

вот код:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace System 
{ 
    public struct Double 
    { 
    unsafe public override int GetHashCode() 
    { 
     fixed (Double* dd = &this) 
     { 
     int* xx = (int*)dd; 
     return xx[0]^xx[1] ; 
     } 

    } 
    } 
} 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     double dd = 123.3444; // line 1 
     // Double dd = 123.3444; // line 2 
     // Cannot implicitly convert type double to System.Double 
     Console.WriteLine(dd.GetHashCode()); 

     Console.ReadLine(); 
    } 
    } 
} 

если я раскомментировать строки 2 я получаю Не удается неявно преобразовать тип двойной в System.Double ошибка. если я запускаю строку 1, то ошибка не возникает, но код переопределения никогда не работает.

Возможно, это очень плохо, что я пытаюсь. поэтому любой знает о алгоритме double.gethashcode, поэтому я могу написать эквивалентный код C++, чтобы получить точное значение int?

ответ

8

Это то, что я вижу Double.GetHashCode():

//The hashcode for a double is the absolute value of the integer representation 
//of that double. 
// 
[System.Security.SecuritySafeCritical] // auto-generated 
public unsafe override int GetHashCode() { 
    double d = m_value; 
    if (d == 0) { 
     // Ensure that 0 and -0 have the same hash code 
     return 0; 
    } 
    long value = *(long*)(&d); 
    return unchecked((int)value)^((int)(value >> 32)); 
} 
+0

И как именно вы планируете переопределить его? ..... -1 извините – leppie

+2

@leppie, вы пропустили часть вопроса OP, где он спрашивает: «Может быть, это очень плохо, что я пытаюсь, поэтому любой знает о алгоритме double.gethashcode, поэтому я могу написать эквивалентный код C++ для получения точной стоимости int? " –

+0

пункт принят +1 :) – leppie

5
public struct Double 

Это первая проблема. Вы не можете переопределить предопределенный тип (если ...).

+0

я попытался с помощью ключевого слова parial (если вы имеете в виду, что). это тоже не сработало. –

+1

Невозможно переопределить примитивные типы и по-прежнему иметь запущенную программу, если вы не предоставили свою собственную среду выполнения .NET. – leppie

+0

Многие коллекции хешей обеспечивают передачу в него настраиваемой хэш-функции. – leppie

2

методы использования расширения, Люк.

2

Существует две проблемы пользовательского двойного типа:

  • Он не содержит никаких данных.
  • Не конвертируется в double.

Первый разрешается путем простого использования частной переменной типа double в структуре.

Вторая решена с использованием неявных преобразователей.

public struct CustomDouble { 

    private double _value; 

    public override int GetHashCode() { 
    byte[] data = BitConverter.GetBytes(_value); 
    int x = BitConverter.ToInt32(data, 0); 
    int y = BitConverter.ToInt32(data, 4); 
    return x^y; 
    } 

    public static implicit operator double(CustomDouble d) { 
    return d._value; 
    } 

    public static implicit operator CustomDouble(double d) { 
    return new CustomDouble() { _value = d }; 
    } 

} 

Пример:

// Use the conversion from double to CustomDouble 
CustomDouble d = 3.14; 

// Use the CustomDouble.GetHashCode method: 
Console.WriteLine(d.GetHashCode()); // 300063655 

// Use the conversion from CustomDouble to double: 
Console.WriteLine(d); // 3.14 
+0

хороший совет, но ваш gethashcode кажется медленнее по сравнению с небезопасной версией. возможно, в моем приложении будет десять тысяч хэширования. Мне нужна скорость. также пользователи будут писать пользовательские коды C#. поэтому им придется использовать имя «CustomDouble» вместо «double». но все равно спасибо. –

+0

@bahadir: Если вам нужна скорость, что плохо, вы можете, конечно, использовать небезопасную версию, я просто включил ее, чтобы показать, что ее можно легко обойти. Аналогичным образом я назвал класс 'CustomDouble', чтобы отделить его от встроенного типа, так как вы должны быть осторожны при попытке их заменить. Вы можете заменить имя «Double», но вы по-прежнему не можете изменить значение ключевого слова 'dobule'. – Guffa

Смежные вопросы