【问题标题】:How to get number at decimal position如何获取小数位的数字
【发布时间】:2019-10-14 13:35:56
【问题描述】:

我正在为微控制器编写 C 代码,以将 GPS 数据格式化为一个 8 字节消息。

我需要对其进行编码并快速解码。 我想这样做: Int32 是 -2147483648 到 2147483647。

我们可以对纬度进行编码: -89599999 到 -89599999 什么是位置 89° 59.9999' S 到 90° 59.9999' N
对于经度: -179599999 到 179599999 什么是位置 179° 59.9999' W 到 179° 59.9999' E

纬度 4 个字节,经度 4 个字节。共 8 字节 CAN 报文。

不用乘除法怎么办?有什么方法可以转移或获得想要的号码 小数位。

我想顺便编码:

unsigned int32 charToInt32(char val)
{
   unsigned int32 valOut;
   valOut = val - '0';
   return valOut;
}

int32 GPS_codeLongitude(char *tab, char dir)
{
   int32 deg = 0;  

   deg  = charToInt32(tab[0]) * 1000000000; 
   deg += charToInt32(tab[1]) * 100000000;
   deg += charToInt32(tab[2]) * 10000000;
   deg += charToInt32(tab[3]) * 1000000;
   deg += charToInt32(tab[4]) * 100000;
   deg += charToInt32(tab[6]) * 10000;
   deg += charToInt32(tab[7]) * 1000;
   deg += charToInt32(tab[8]) * 100;
   deg += charToInt32(tab[9]) * 10; 
   deg += charToInt32(tab[10]); 

   if(dir == 'S') deg = -deg;
   return deg;
}

int32 GPS_codeLatitude(char *tab, char dir)
{
   int32 deg = 0;  

   deg  = charToInt32(tab[0]) * 100000000; 
   deg += charToInt32(tab[1]) * 10000000;
   deg += charToInt32(tab[2]) * 1000000;
   deg += charToInt32(tab[3]) * 100000;
   deg += charToInt32(tab[5]) * 10000;
   deg += charToInt32(tab[6]) * 1000;
   deg += charToInt32(tab[7]) * 100;
   deg += charToInt32(tab[8]) * 10;
   deg += charToInt32(tab[9]) ; 

   if(dir == 'W') deg = -deg;
   return deg;
}

【问题讨论】:

  • 你怎么知道179599999代表17.9599999还是179.599999?为什么不使用两个 float 值?正如您的代码所尝试的那样,您无法将 10 个十进制数字精确地存储在 32 位中。
  • 你的输入数据是不是像char tab[] = "179599999"; for 179°59.9999'?你试过atoi()吗?
  • @WeatherVane: 179599999 是九位数,而不是十位数。即使它是 10(附加了另外 9 个),它也适合 32 位,即使带有符号位。而float 不适合这个。
  • @EricPostpischil 请仔细阅读从第 11 行到第 20 行发布的代码。
  • @WeatherVane:啊,你是对的,代码与问题文本不匹配。尽管如此,1,795,999,999 适合 31 位。

标签: c gps can-bus


【解决方案1】:

这是一种方法:

static void int2str(char *buf, unsigned int x)
{
    const unsigned int divs[] = { 1000000000, 100000000, 10000000, 1000000,
     100000, 10000, 1000, 100, 10 };
    for (int i = 0; i < sizeof divs / sizeof *divs; ++i)
    {
        unsigned char digit = '0';
        while (x >= divs[i])
        {
            ++digit;
            x -= divs[i];
        }
        *buf++ = digit;
    }
    *buf++ = '0' + x;
    *buf = '\0';
}

这将向左补零,但这通常适用于计算机对计算机的对话。此外,它不使用任何乘法或除法,但它非常迭代,所以不是很快...

【讨论】:

    【解决方案2】:

    使用 atoi 和按位运算的示例:

    #define CanMessageLen 8
    #define NIBBLELEN 4
    typedef char CanMessage[CanMessageLen];
    
    
    typedef enum
    {
        NORTH,
        SOUTH
    } LatitudeDir;
    
    typedef enum
    {
        EAST,
        WEST
    } LongitudeDir;
    
    CanMessage* CoordinatesToMsg(char* latitude, LatitudeDir latitudedir, char* longitude , LongitudeDir longitudedir)
    {
        CanMessage canMessage = { 0 };
        __int32 latitudeInt=0;
        __int32 longitudeInt = 0;
    
        latitudeInt = atoi(latitude);
        longitudeInt = atoi(longitude);
    
        if (latitudedir == SOUTH)
        {
            latitudeInt = -latitudeInt;
        }
        if (longitudedir == WEST)
        {
            longitudeInt = -longitudeInt;
        }
    
        for (size_t i = 0; i < 4; i++)
        {
            canMessage[i] = (char)(latitudeInt >> (8 * i) & 0xff);
            canMessage[i+4] = (char)(longitudeInt >> (8 * i) & 0xff);
        }
        return canMessage;
    }
    

    示例 -80° 55.9999' 150° 55.9999

    char latitude[10] = { '0','8','0','5','5','9','9','9','9','\0'}; 
    char longitude[10] = { '1','5','0','5','5','9','9','9','9','\0'}; 
    
    CoordinatesToMsg(latitude, SOUTH,longitude, EAST);
    

    输出[0x81,0xC0,0x32, 0xFB, 0xFF, 0x5C, 0xF9, 0x08] //小端序

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-15
      • 2020-09-30
      • 2011-01-26
      • 2010-11-12
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多