Нужен детерминированный алгоритм для генерации префикса домена ресурса для заданного пути равномерно распределенным способом - PullRequest
4 голосов
/ 04 декабря 2009

Мне нужно сгенерировать префикс домена ресурса на основе заданного пути и настроенного количества доменов ресурса детерминированным способом с хорошим распределением. Например, если вы передадите ему путь «/script/site.js», он вернет «res #», где «#» - это целое число от 0 до заданного количества доменов ресурсов.

Использование C # 3.0.

Пока есть это:

var resourceDomainCount = 4;
var hasher = System.Security.Cryptography.SHA1.Create();
var paths = new [] {
    "/App_Themes.0.1.433.232/images/buttonsBackgrounds.jpg",
    "/App_Themes.0.1.433.232/images/blahblah.jpg",
    "/App_Themes.0.1.433.232/images/pagebg.gif",
    "/App_Themes.0.1.433.232/site.css",
    "/script/site.js",
    "/App_Themes.0.1.433.232/images/different.jpg",
    "/App_Themes.0.1.433.232/images/shadows.jpg",
    "/Handlers/ImageHandler.ashx?type=l&id=123&s=g&index=0",
    "/Handlers/ImageHandler.ashx?type=l&id=234&s=g&index=0",
    "/Handlers/ImageHandler.ashx?type=l&id=345&s=g&index=0",
    "/Handlers/ImageHandler.ashx?type=p&id=MyProduct&s=g&index=0",
    "/Handlers/ImageHandler.ashx?type=p&id=WineGreat&s=g&index=0",
    "/Handlers/ImageHandler.ashx?type=p&id=YayYay&s=g&index=0"
    };
foreach (var path in paths) {
    var pathHash = hasher.ComputeHash(Encoding.ASCII.GetBytes(path));
    var singleByteHash = pathHash.Aggregate(0, (a, b) => a ^ b);
    var random = new Random((int)singleByteHash);
    var resourceDomainIndex = random.Next(0, resourceDomainCount);
    (resourceDomainIndex + ": " + path).Dump();
}

Который производит следующее:

3: /App_Themes.0.1.433.232/images/buttonsBackgrounds.jpg
0: /App_Themes.0.1.433.232/images/blahblah.jpg
1: /App_Themes.0.1.433.232/images/pagebg.gif
1: /App_Themes.0.1.433.232/site.css
3: /script/site.js
1: /App_Themes.0.1.433.232/images/different.jpg
3: /App_Themes.0.1.433.232/images/shadows.jpg
1: /Handlers/ImageHandler.ashx?type=l&id=123&s=g&index=0
1: /Handlers/ImageHandler.ashx?type=l&id=234&s=g&index=0
0: /Handlers/ImageHandler.ashx?type=l&id=345&s=g&index=0
2: /Handlers/ImageHandler.ashx?type=p&id=MyProduct&s=g&index=0
1: /Handlers/ImageHandler.ashx?type=p&id=WineGreat&s=g&index=0
0: /Handlers/ImageHandler.ashx?type=p&id=YayYay&s=g&index=0

Не получается нужный мне дистрибутив (там только один экземпляр '2').

Существуют тысячи входных строк, которые постоянно меняются, и пути будут генерироваться во время выполнения, например: <a href="<%= GetPath("/script/site.js") %>">Link</a>

Ответы [ 2 ]

4 голосов
/ 04 декабря 2009

Это намного проще, чем хэширование строки (ну, по-видимому, в любом случае это уже хэш), и кажется , чтобы получить лучшее распределение:

Math.Abs(path.GetHashCode()) % resourceDomainCount
1 голос
/ 04 декабря 2009

Ваш образец слишком маленький. Случайность, как правило, похожа на статистику. Это подтверждается только в течение длительного периода времени. Попробуйте перезапустить ваш код за 100 итераций и посмотрите, появляется ли каждое значение примерно одинаковое количество времени. Затем попробуйте еще раз для 10 000 итераций и обратите внимание, что фактическое количество результатов ближе к проценту. Затем запустите его на 1 миллион итераций и обратите внимание, что это еще ближе. Он никогда не должен быть точно таким же, иначе он не был бы случайным.

И если результаты не соответствуют этому шаблону, то, возможно, у вас есть проблема даже с распределением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...