Преобразование в целые веса из числа с плавающей запятой - PullRequest
0 голосов
/ 03 июля 2019

Итак, у меня есть этот класс с именем ProbabilisticEnumerator , он принимает карту элементов и целочисленные веса.Смотрите следующий пример:

var myProbabilityTable = new Dictionary<char, uint> {
    { 'A', 1 }, // 14.29%
    { 'B', 2 }, // 28.57%
    { 'C', 4 }, // 57.14%
};

Я пытаюсь найти эффективный способ инвертировать это так, чтобы можно было передавать значения на основе числа с плавающей запятой (что может быть более естественным для некоторых).Вот пример того, что я мог бы иметь в виду:

var myProbabilityTable = new Dictionary<char, float> {
    { 'A', 0.1429f }, // 1
    { 'B', 0.2857f }, // 2
    { 'C', 0.5714f }, // 4
};

До сих пор лучшее, что я смог придумать, - это подход, который занимает минимум два прохода;первый, чтобы получить общий вес, и второй, чтобы создать новый словарь.Есть ли лучший способ сделать это?Я пропускаю какие-либо крайние случаи, которые могли бы заставить вещи "взорваться?"

Моя попытка:

class Program {
    static void Main(string[] args) {
        var floatWeights= new Dictionary<string, float> {
            { "A", 25.0f },
            { "B", 60.0f },
            { "C", 15.0f },
        };
        var integerWeights = ConvertFloatWeightsToInteger(floatWeights);

        foreach(var item in integerWeights) {
            Console.WriteLine(item);
        }
    }

    static Dictionary<T, int> ConvertFloatWeightsToInteger<T>(Dictionary<T, float> elementWeights) {
        var totalWeight = 0f;

        foreach (var weight in elementWeights.Values) {
            if (float.IsNegative(weight) || float.IsSubnormal(weight)) {
                throw new ArgumentOutOfRangeException(actualValue: weight, message: "weight must be a positive normal floating-point number", paramName: nameof(weight));
            }

            totalWeight += weight;
        }

        return elementWeights.ToDictionary(
            keySelector: k => k.Key,
            elementSelector: e => ((int)((e.Value / totalWeight) * 1000000000))
        );
    }
}
...