Как привести float к int в C #, чтобы он выводил то же значение, что и float.ToString ()? - PullRequest
0 голосов
/ 02 мая 2018

При вызове ToString() на неточных числах с плавающей запятой получаются числа, которые может ожидать человек (например, 4.999999 ... печатается как 5). Однако при приведении к int дробная часть отбрасывается, и в результате получается целое число, уменьшенное на 1.

float num = 5f;
num *= 0.01f;
num *= 100f;
num.ToString().Dump(); // produces "5", as expected
((int)num).ToString().Dump(); // produces "4"

Как мне привести число с плавающей точкой к int, чтобы я получил дружественную человеку ценность, которую производит float.ToString()?

Я использую этот грязный хак:

int ToInt(float value) {
    return (int)(value + Math.Sign(value) * 0.00001);
}

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


Редактировать: Мне хорошо известны причины, по которым числа с плавающей точкой обрезаются в том виде, в каком они есть (4.999 ... до 4 и т. Д.). Вопрос заключается в приведении к int при эмуляции поведения по умолчанию System.Single.ToString ()

Чтобы лучше проиллюстрировать поведение, которое я ищу:

-4.99f должно быть приведено к -4
4.01f должно быть приведено к 4
4.99f должно быть приведено к 4
4.999999f должно быть приведено к 4
4.9999993f должен быть приведен к 5

Это то же поведение, что и ToString.

Попробуйте запустить это:

float almost5 = 4.9999993f;
Console.WriteLine(almost5); // "5"
Console.WriteLine((int)almost5); // "4"

Ответы [ 3 ]

0 голосов
/ 02 мая 2018

Может быть, вы ищете это:

Convert.ToInt32 (поплавок)

источник

0 голосов
/ 03 мая 2018

Пока что лучшим решением кажется решение вопроса.

int ToInt(float value) {
    return (int)(value + Math.Sign(value) * 0.000001f);
}

Это эффективно привязывает значение к ближайшему целому, если разница достаточно мала (меньше 0.000001). Однако эта функция отличается от поведения ToString и немного более терпима к неточностям.

Другим решением, предложенным @ chux , является использование ToString и анализ строки обратно. Использование Int32.Parse вызывает исключение, когда число имеет десятичную точку (или запятую), поэтому вам нужно оставить только целую часть строки, и это может вызвать другие проблемы в зависимости от значения по умолчанию CultureInfo.

0 голосов
/ 02 мая 2018

0.05f * 100 не совсем 5 из-за округления с плавающей запятой (на самом деле это значение 4.999998 .... если выражено как число с плавающей запятой

Ответ таков: в случае (int)(.05f * 100) вы берете значение с плавающей запятой 4.999998 и усекаете его до целого числа, что приводит к 4.

Так что используйте Math.Round. Функция Math.Round округляет значение с плавающей точкой до ближайшего целого числа и округляет значения средней точки до ближайшего четного числа.

    float num = 5f;
    num *= 0.01f;
    num *= 100f;
    Console.WriteLine(num.ToString());
    Console.WriteLine(((int)Math.Round(num)).ToString());
...