2010-06-17 2 views
0

Я хотел бы обрезать поплавок до 4 цифр. Есть ли эффективный способ сделать это? Мое текущее решение:C++: как эффективно усекать двойной?

double roundDBL(double d,unsigned int p=4) 
{ 
unsigned int fac=pow(10,p); 
double facinv=1.0/static_cast<double>(fac); 
double x=static_cast<unsigned int>(d*fac)*facinv; 
return x; 
} 

но с использованием pow и удаления, мне кажется, не так эффективно.

вид с уважением

Arman.

+0

Вам действительно нужно усечь значение, а не его отображение? Вы не сможете получить точное значение, скажем, 0,0001. –

+0

Мне нужно усечь его, я буду использовать его для расчетов не только для отображения. – Arman

+1

Вы имели в виду 'double x = static_cast (d * fac) * facinv;'? –

ответ

4
round(d*10000.0)/10000.0; 

или если p должно быть переменным;

double f = pow(10,p); 
round(d*f)/f; 

round обычно составляется в виде одной команды, которая быстрее, чем преобразование в целое число и обратно. Профиль для проверки.

Обратите внимание, что double может не иметь четкого представления до 4 знаков после запятой. Вы действительно не сможете урезать произвольный двойник, просто найдите ближайшее приближение.

+0

Да! Профилирование показывает, что это быстрее, чем моя версия, спасибо! – Arman

2

Эффективность зависит от вашей платформы.

Каких бы методы ни старайтесь, вы должны профилем, чтобы убедиться, что

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

Вы можете умножить на 10000, усечь как целое число и разделить снова. Преобразование между двойным и int может быть быстрее или медленнее для вас.

Вы можете обрезать на выходе, например. a printf строка формата "%.4f"

+0

Платформа Linux 64bit. – Arman

1

Вместо этого вы можете заменить pow на более эффективный вариант с целым числом. Там есть один из переполнения стека: The most efficient way to implement an integer based power function pow(int, int)

Также, если вы можете принять некоторую неточность, замените разницу на умножение. Разделы - одна из самых медленных общих математических операций.

Кроме этого, я буду отгонять то, что говорили другие, и просто усекать на выходе, если вам не нужно использовать усеченный двойной в вычислениях.

+0

Очень полезная ссылка, спасибо! – Arman

1

Если вам нужно выполнить точные вычисления, содержащие десятичные цифры, тогда прекратите использование double прямо сейчас! Это не правильный тип данных для вашей цели. Вы не будете получите фактически округленные десятичные значения. Почти все значения будут (после усечения, неважно, какой метод вы используете) на самом деле будут чем-то вроде 1000999999999999841, а не 1,0001.

Это потому, что double реализован с использованием binary fractions, а не десятичных. Вместо этого вы можете использовать decimal types, который будет работать правильно. Они будут намного медленнее, но тогда, если результат не должен быть правильным, я знаю способ сделать его бесконечно быстрым ...

+0

Какой метод? ;) – Alex

+0

Те вычисления выполняются в двойном порядке, затем я быструю визуализацию с использованием opengl, там мне не нужна точность после 3,4-й цифры. «Я знаю метод, чтобы сделать его бесконечно быстрым ...» - не могли бы вы поделиться этим методом? Спасибо. – Arman

+0

@Arman: Если вам не нужна точность после этих цифр, в чем смысл их усечения? Почему бы просто не оставить их, если они не имеют значения? Что касается последнего: если вычисления не должны быть правильными, вы можете просто скопировать произвольный результат и ничего не вычислять. Еще один способ сказать: «Самая важная оптимизация - это то, что программа идет от нерабочего к работе». –

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