В этом конкретном случае это потому, что .09 и .999999 не могут быть представлены с точной точностью в двоичном формате (аналогично, 1/3 не может быть представлена с точной точностью в десятичной форме). Например, 0.11111111111111111111101111 base 2 является 0.999998986721038818359375 базой 10. Добавление 1 к предыдущему двоичному значению, 0.11111111111111111111 base 2 - 0.99999904632568359375 base 10. Для точно 0,999999 нет двоичного значения. Точность плавающей точки также ограничена пространством, выделенным для хранения экспоненты и дробной части мантиссы. Кроме того, как и целые типы, плавающая точка может переполнять свой диапазон, хотя его диапазон больше целых.
Запуск этого бита кода C ++ в отладчике Xcode,
float myFloat = 0,1;
показывает, что myFloat получает значение 0.100000001. Он отключен на 0.000000001. Не так много, но если вычисление имеет несколько арифметических операций, то погрешность может быть усугублена.
imho очень хорошее объяснение с плавающей точкой в главе 14 из Введение в компьютерную организацию с x86-64 Assembly Language & amp; GNU / Linux Боба Планца из Калифорнийского государственного университета в Сономе (отставной) http://bob.cs.sonoma.edu/getting_book.html . Ниже приведена эта глава.
Плавающая точка похожа на научную нотацию, где значение хранится как смешанное число, большее или равное 1.0 и меньше 2.0 (мантисса), разное число до некоторая мощность (экспонента). Плавающая точка использует базу 2, а не базу 10, но в простой модели Plantz дает, он использует базу 10 для ясности. Представьте себе систему, в которой для мантиссы используются два положения хранения, одна позиция используется для знака показателя * (0, представляющего + и 1, представляющего -), а для экспонента используется одна позиция. Теперь добавьте 0.93 и 0.91. Ответ 1,8, а не 1,84.
9311 представляет собой 0,93 или 9,3 раза 10 к -1.
9111 представляет собой 0,91 или 9,1 раза 10 к -1.
Точный ответ равен 1,84, или 1,84 раза 10 до 0, что было бы 18400, если бы у нас было 5 позиций, но, имея только четыре позиции, ответ равен 1800, или 1,8 раза 10 до нуля, или 1,8. Конечно, типы данных с плавающей запятой могут использовать более четырех позиций хранения, но количество позиций по-прежнему ограничено.
Не только точность ограничена пространством, но «точное представление дробных значений в двоичном формате ограничивается суммами обратных степеней двух »(Plantz, op. cit.).
0,11100110 (двоичный) = 0,89843750 (десятичный)
0,11100111 (двоичный) = 0,90234375 ( decimal)
Точного представления десятичного десятичного числа в двоичном выражении нет. Даже перенос фракции из большего количества мест не работает, так как вы получаете право повторять 1100 навсегда.
Начальные программисты часто видят арифметику с плавающей точкой как более точную, чем целую. Верно, что даже добавление двух очень больших целых чисел может привести к переполнению. Умножение делает еще более вероятным, что результат будет очень большим и, следовательно, переполнением. И когда используется с двумя целыми числами, оператор / в C / C ++ приводит к потере дробной части. Однако ... представления с плавающей точкой имеют свой собственный набор неточностей. (Plantz, op. Cit.)
blockquote>* В плавающей точке представлены как знак числа, так и знак экспоненты.
Мое решение: программа содержит только один файл языковых ресурсов по умолчанию (resx). Все остальные языки скомпилированы из .resx в .resources и встроены в файл ресурсов. Важный! Я изменил расширение, потому что «.resources» распознается как особый тип ресурса, поэтому мои французские файлы называются «PIAE.LangResources.fr».
Вот простой код для извлечения переведенной строки (его следует улучшить с помощью кэширования значений из ресурса):
internal static string GetString(string str, string lang)
{
if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("empty language query string");
if (string.IsNullOrEmpty(lang)) throw new ArgumentNullException("no language resource given");
// culture-specific file, i.e. "LangResources.fr"
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PIAE.LangResources."+lang);
// resource not found, revert to default resource
if (null == stream)
{
stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PIAE.Properties.LangResources.resources");
}
ResourceReader reader = new ResourceReader(stream);
IDictionaryEnumerator en= reader.GetEnumerator();
while (en.MoveNext())
{
if (en.Key.Equals(str))
{
return en.Value.ToString();
}
}
// string not translated, revert to default resource
return LangResources.ResourceManager.GetString(str);
}
Используйте эту программу, она работает со мной: EXEPack
Вам просто нужно делать это вручную каждый раз, когда вы компилируете, не уверен, что есть командный инструмент.
Вы не нашли его, потому что это не так, как работает платформа .NET. .NET ожидает вспомогательные библиотеки DLL в специально названном месте (каталоги iow, названные в соответствии с языком содержащихся в них ресурсов, например, de
, de-DE
, chs
, ...). Если вы не будете работать таким образом, .NET не сможет применить свою магию (которая должна автоматически выбрать правильный ресурс в соответствии с текущей культурой пользовательского интерфейса: Thread.CurrentThread.CurrentUICulture
).