Это необычный способ представления времени.
В любом случае, есть два простых способа сделать это в любом случае, если у вас есть 64-битные целые числа или числа с плавающей запятой (первые более вероятны во встроенной системе):
/* assuming long is 64-bit and int is 32-bit
or in general long twice the size of int: */
Fraction = (long) tv_usec * UINT_MAX / 1000000 /* usecs to fraction */
tv_usec = (long) Fraction * 1000000 / UINT_MAX /* fraction to usecs */
/* assuming floating points are available: */
Fraction = tv_usec * ((double) UINT_MAX / 1000000) /* usecs to fraction */
tv_usec = Fraction * ((double) 1000000 / UINT_MAX) /* fraction to usecs */
Очевидно, что оба являются только целочисленными приближениями, потому что большинство значений в одной шкале не могут быть представлены как целые числа в другой шкале. И в одном направлении вы можете потерять некоторую точность, потому что форма Fraction
может представлять гораздо более мелкие времена - один шаг формы Fraction
составляет менее 0,00024 микросекунд. Но это только в том случае, если ваш таймер может измерять эти значения, что маловероятно - большинство таймеров не могут измерять даже в масштабе микросекунд, а значение, которое вы видите в tv_usec
, часто округляется.
Если ни 64-разрядные целые числа, ни числа с плавающей запятой не доступны, вы можете сделать это итеративно с дополнительной переменной. Я подумал, есть ли более простой (и менее дорогой, учитывая, что это временный код) способ сделать такое масштабирование, чем делать эквивалент итеративного 64-разрядного умножения и деления с двумя 32-разрядными целыми числами. Из двух идей, которые пришли мне в голову, одна не будет выполнять даже точное масштабирование и может дать результаты с отклонением до 9 бит, а та, которая компенсирует это, оказывается не дешевле. Если у меня возникнет что-то новое, я опубликую это здесь, но это интересная задача. У кого-нибудь еще есть хороший алгоритм или фрагмент? Возможно, с помощью небольшого предварительно вычисленного стола?