Итак, у меня есть этот класс с именем 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))
);
}
}