2010-06-16 3 views
2

Я хотел бы реализовать функцию frac в C# (точно так же, как в hsl здесь http://msdn.microsoft.com/en-us/library/bb509603%28VS.85%29.aspx), но поскольку это приложение с очень интенсивным процессором, я бы хотел, чтобы лучшая версия была возможна. Я использую что-то вродеСамая быстрая реализация функции frac в C#

public float Frac(float value) 
{ 
    return value - (float)Math.Truncate(value); 
} 

но у меня возникают проблемы точности, например, для 2.6f это возвращение в модульном тесте

Ожидаемое: 0.600000024f Но был: 0.599999905f

Я знаю, что я могу преобразовать в десятичное значение, а затем в конце обращенным плавать, чтобы получить правильный результат что-то вроде этого:

public float Frac(float value) 
{ 
    return (float)((decimal)value - Decimal.Truncate((decimal)value)); 
} 

Но мне интересно, если есть лучший ва y, не прибегая к десятичным знакам ...

ответ

0

Вы собираетесь должны использовать десятичные как в:

public decimal Frac(decimal value) { return value - Math.Truncate(value); } 

Итак, когда вы проходите 2.6м вы всегда получить +0,6

+0

Я думаю, что пока буду использовать десятичные числа. По крайней мере, до тех пор, пока не найдет отбойник и самое быстрое решение ... –

+0

Я закончил использование (float) ((десятичное) значение% 1,0 м), которое, я думаю, все еще медленное, но, по крайней мере, работает –

2

float (псевдоним для System.Single) является точной точностью до 7 цифр. В любом случае вы не должны сравнивать значения с плавающей запятой, используя равенство. Вместо этого вы должны проверить, что они находятся в допустимом диапазоне - например, разница между ожидаемыми и фактическими значениями не более 0,000001.

Assert.AreEqual(expected, actual, delta); 

Если вы используете double вместо этого, вы будете точны до 15-16 цифр.

+0

я не знаю, если он нуждается в этом, но , в этом случае он не может определить разницу между 2.5999999999 и 2.6 и 2.600000001 и т. д. Десятичный должен быть способ пойти сюда. – Recep

+0

Если вы имеете дело с истинными типами с плавающей запятой (какой десятичной точкой нет), то * * не имеет значимой разницы между 2.5999999999 и 2.6, если разница превышает точность, разрешенную типом. Использование decimal медленнее и имеет гораздо более высокую стоимость хранения, которая может не понадобиться, если дополнительная точность не требуется. – Josh

+0

Моя проблема в том, что мне не нужна дополнительная точность. Я видел сообщения, которые прибегают к трюкам со строками, которые могут достичь того же результата, но я упал, это не самое быстрое решение. Самый лучший путь до сих пор - десятичный. Мне было интересно только, если есть какой-то умный трюк с математикой, который мог бы сделать это быстрее в C# –

Смежные вопросы