2010-01-27 3 views
4

Я следую за учебниками для начинающих для OpenGL в C++, но по мере того, как я начинал программировать на C#, это заставило меня взять много вещей как само собой разумеющееся. Таким образом, моя проблема возникла, когда я отлаживал печать своего показания FPS на выходе. Я думаю, что метод был чем-то вроде DebugPrintString с верхней части головы, который взял char *, и в основном я печатал «FPS: x». Я использовал scanf_s, чтобы поместить значение fps в массив символов, но это - то, где моя проблема. Насколько велик массив символов?Подсчет цифр в поплавке

Позвольте мне подробнее рассказать следующее: чтение FPS хранится как поплавок, поскольку кадры/секунды обычно заканчиваются не хорошим числом. Таким образом, моего номера может быть 60, или это может быть 59.12345. 60 потребуется всего 2 байта, а 59.12345 - 8 (1 за период). Поэтому я подумал: «О, хорошо, мне нужно подсчитать количество цифр, никаких проблем!» Мальчик был я в шоке.

Я сделал способ подсчета цифр, считая левую сторону десятичной точки, было легко, просто прежде всего, чтобы сделать его как int, чтобы удалить десятичные точки и делить на 10 (на самом деле, я думаю, биты) и подсчитать количество раз, когда я могу сделать это, пока не достигнет 0. И теперь, чтобы подсчитать цифры с правой стороны, ну, я просто умножусь на 10, вычтем цифру и сделаю это, пока не достигнет нуля , Метод, как правило, возвращает 32, я думаю, что это так. Итак, я WTF'd и посмотрел на него в отладке, получается, когда вы умножаете float, эффективно перемещая столбцы цифр из-за известной проблемы точности, она просто добавила другую цифру!

Я сделал несколько крупных поисковых запросов, но не смог найти ничего выше char str [128] и scanf, если в этом случае strlen (str) минус 1 (нулевой терминатор). Но я надеялся на более элегантное решение. В конце концов, я просто запустил его как int и допустил достаточно для 9999 кадров в секунду, также добавил чек, чтобы узнать, есть ли fps> 9999, но я не думаю, что это когда-нибудь произойдет. Лучше перестраховаться, чем SEG FAULT :(

TLDR: Есть ли способ, чтобы получить количество цифр в обращении Как зсапЕ это сделать ?!

Извините за длинный пост, просто хотел поделиться своей фрустрацией>? : D

Edit:.. орфографические ошибки

+2

sprintf? Это предложение является наполнителем. – recursive

+0

Простите, что вы имеете в виду? Это было слишком долго? да ха-ха извините: P – daniel

+2

«Рекурсивный» необходимо записать не менее 15 символов в своем комментарии. "Sprintf?" всего восемь. – John

ответ

7

Учитывая это C++, мы говорим о , почему бы не пойти STL-способом?

Precision 5 мест после десятичной точки, может быть переменное количество символов:

std::stringstream ss; 
ss << std::setprecision (5) << std::fixed << f; 
std::string fps = ss.str(); 

максимальная точность 5 значащих цифр:

std::stringstream ss; 
ss << std::setprecision (5) << f; 
std::string fps = ss.str(); 
+1

О, конечно, получите все на нас. ;) (+1 BTW) – John

+0

Прохладное спасибо за альтернативное решение :) Я никогда не попадал в std :: string, я только начинающий, и я начал с некоторых учебных пособий. Думаю, я никогда не выходил из привычки char * lol. – daniel

+0

@ daniel - пришло время сделать это, вы сэкономите много времени и нервов:> –

6

вы можете укоротить/заставить число с плавающей запятой в любой точности вы хотите использовать Sprintf Тогда проблема уходит

+0

О, это было бы здорово, как я могу это сделать? – daniel

+0

Вот ссылка: http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/ Вы можете изменить часть% f, чтобы точно указать точность. – John

+0

+1: для непринужденного традиционного решения:> –

0

Это кадров в секунду. Просто используйте три цифры слева и один справа, кто заботится о том, что думает о плавающей точке, кажется, ниже десятого места?

EDIT в ответ на первый комментарий.

http://en.wikipedia.org/wiki/Floating_point

Если мы действительно после того, как количество цифр в обращении, мы должны знать, как поплавки работу. Точное значение, представленное стандартным типом данных float стандарта IEEE, имеет определенное количество бит, обычно 32 или 64, которые стандартно распределяются, чтобы дать вам определенное количество значимых цифр, а также некоторый показатель мощности, чтобы масштабировать его вверх или вниз.24 бита значащих цифр выходят примерно в семь мест по десятичным знакам. В конце курса всегда будет какая-то форма усечения или округления (например, как одна треть, написанная в десятичной форме, всегда округляется, когда вы прекращаете писать повторяющиеся тройки).

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

+0

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

1

Поскольку числа с плавающей запятой не сохраняются ни в каком конкретном виде, на самом деле нет эффективного способа подсчета количества цифр. То, что вы, вероятно, хотите сделать, это контролировать длину числа, которое предоставляет float, и использовать буфер с фиксированным размером.

С printf(), scanf() и связанными с ним функциями размер числа с плавающей запятой можно указать, изменив спецификатор типа формата. В то время как простой %f может быть наиболее распространенным, он может быть использован более гибко, добавляя модификаторы между % и f, такие как:

%[width][.precision]f 

, где [width] относится к минимальным количество цифр, отображаемых для номер (при его отсутствии не будет усечения), а [.precision] указывает точное количество цифр, отображаемых после десятичной точки.

В качестве примера, вы можете изучить вывод следующей программы:

#include <cstdio> 

using std::printf; 
int main() { 
    float f(59.12345); 

    printf("[%f]\n", f); // [59.123451] 
    printf("[%15f]\n", f); // [  59.123451] 
    printf("[%1f]\n", f); // [59.123451] 
    printf("[%.2f]\n", f); // [59.12] 
    printf("[%6.2f]\n", f); // [ 59.12] 
    printf("[%4.1f]\n", f); // [59.1] 
} 

Точного размера массива символов все равно будет изменяться в зависимости от значения до десятичного знака. Но пока вы можете контролировать ширину и точность, выделение достаточной памяти в массив символов (или установка числа в массив фиксированной длины) должно быть существенно проще.

0

Ну John at CashCommons дал традиционный ответ, просто используйте квалификаторы формата printf, чтобы установить определенную ширину. Обычно я нахожу, что 2 десятичных разряда достаточно для частоты кадров. Он позволяет различать 30 fps и 29.97 fps, два наиболее распространенных значения.

sprintf (buffer, "%.2f", fps); 

Но если вы хотите знать, что такое ПРИМЕРНЫЙ случай, существует также способ узнать это. Оформить заказ http://en.wikipedia.org/wiki/IEEE_754-2008.

Это показывает, что значения с плавающей запятой (32-битные поплавки) содержат 24 двоичных разряда в мантиссе, которые работают до 7,255 десятичных цифр, назовите ее 8. Добавьте 5 цифр для показателя, 1 для знака, 1 для ведущие 0, 1 для десятичной точки, и вы получите

1 + 1 + 8 + 5 = 15 characters 

добавить номер для завершающего нуля, и вы получите 16 цифр.

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