简体   繁体   English

在uint32_t计算中转换为float

[英]Conversion to float in uint32_t calculation

I am trying to improve a SWRTC by modifying the definition of a second ( long unsigned n_ticks_per_second ) by synchronizing time with a server. 我正在尝试通过与服务器同步时间来修改秒( 长unsigned n_ticks_per_second )的定义来改进SWRTC。

#include <stdint.h>
#include <stdio.h>

int main(int argc, char * argv[]){

    int32_t total_drift_SEC;
    int32_t drift_per_sec_TICK;
    uint32_t at_update_posix_time = 1491265740;
    uint32_t posix_time = 1491265680;
    uint32_t last_update_posix_time = 1491251330;
    long unsigned n_ticks_per_sec = 1000;

    total_drift_SEC = (posix_time - at_update_posix_time);
    drift_per_sec_TICK = ((float) total_drift_SEC) / (at_update_posix_time - last_update_posix_time);

    n_ticks_per_sec += drift_per_sec_TICK;

    printf("Total drift sec %d\r\n", total_drift_SEC);
    printf("Drift per sec in ticks %d\r\n", drift_per_sec_TICK);
    printf("n_ticks_per_second %lu\r\n", n_ticks_per_sec);

    return 0;

}

What I don't understand is that I need to cast total_drift_SEC to float in order to have a correct result in the end, ie to have n_ticks_per_sec equal to 1000 in the end . 我不明白的是,我需要将total_drift_SEC强制转换float ,以便最终获得正确的结果, 即,使end等于n_ticks_per_sec

The output of this code is: 此代码的输出是:

Total drift sec -60 总漂移秒-60

Drift per sec in ticks 0 每秒滴答滴答声0

n_ticks_per_second 1000 n_ticks_per_second 1000

Whereas the output of the code without the cast to float is: 而没有强制转换为float的代码的输出为:

Total drift sec -60 总漂移秒-60

Drift per sec in ticks 298054 每秒滴答滴答度298054

n_ticks_per_second 299054 n_ticks_per_second 299054

This line 这条线

drift_per_sec_TICK = total_drift_SEC / (at_update_posix_time - last_update_posix_time);

divides a 32 bit signed int by a 32 bit unsigned int . 将32位有signed int除以32位unsigned int

32 bit unsigned int has a higher rank then 32 bit signed int . 32位unsigned int的等级高于32位signed int等级。

When doing arithmetic operations the " Usual Arithmetic Conversions " are applied: 在进行算术运算时,将应用“ 通常的算术转换 ”:

From the C11 Standard (draft) 6.3.1.8/1 : 根据C11标准(草稿)6.3.1.8/1

if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type. 如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则将带符号整数类型的操作数转换为无符号整数类型的操作数的类型。

So -60 gets converted to a (32 bit) unsigned int : 4294967236 因此-60被转换为(32位) unsigned int4294967236

Here 这里

drift_per_sec_TICK = (float) total_drift_SEC / (at_update_posix_time - last_update_posix_time);

The following applies (from the paragraph of the C Standard as above): 以下内容适用(根据上述C标准的段落):

if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float . 如果一个操作数的对应实型为float,则另一个操作数将转换为对应的实型为float的类型,而不会改变类型域。


To not blindly step into those traps always specify -Wconversion when compiling with GCC. 要避免盲目进入这些陷阱, -Wconversion在使用GCC进行编译时始终指定-Wconversion

Because with "integer" version total_drift_SEC will become unsigned so -60 --> 4294967236 因为使用“整数”版本, total_drift_SEC版本将变为unsigned所以-60 > 4294967236

4294967236 / 14410 = 298054

Using float the division will calculate: 使用浮点除法将计算:

-60/14410 = 0

Referring to the c-standard at page 53 请参阅第53页的c-标准

6.3.1.8 Usual arithmetic conversions 6.3.1.8常规算术转换

1 Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. 1许多期望算术类型的操作数的运算符都以类似的方式引起转换和产生结果类型。 The purpose is to determine a common real type for the operands and result. 目的是确定操作数和结果的通用实型。 For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type. 对于指定的操作数,在不更改类型域的情况下,将每个操作数转换为其对应的实型为普通实型的类型。 Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result, whose type domain is the type domain of the operands if they are the same, and complex otherwise. 除非另有明确说明,否则普通实型也是结果的相应实型,如果操作数相同,则其类型域为操作数的类型域,否则为复杂。 This pattern is called the usual arithmetic conversions: [...] Otherwise, the integer promotions are performed on both operands. 此模式称为通常的算术转换:[...]否则,将对两个操作数执行整数提升。 Then the following rules are applied to the promoted operands: 然后,将以下规则应用于提升后的操作数:

  • If both operands have the same type, then no further conversion is needed. 如果两个操作数具有相同的类型,则无需进一步转换。 Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank. 否则,如果两个操作数都具有符号整数类型或都具有无符号整数类型,则将具有较小整数转换等级的操作数转换为具有较大等级的操作数的类型。
  • Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type. 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则将带符号整数类型的操作数转换为无符号整数类型的操作数的类型。
  • Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type. 否则,如果带符号整数类型的操作数的类型可以表示带无符号整数类型的操作数的所有值,则带无符号整数类型的操作数将转换为带符号整数类型的操作数的类型。
  • Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. 否则,两个操作数都将转换为与带符号整数类型的操作数类型相对应的无符号整数类型。

Ephasis mine Ephasis地雷

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM