搜索
bottom↓
回复: 15

求救! 数据类型不够,如何处理.

[复制链接]

出0入0汤圆

发表于 2013-10-15 14:55:38 | 显示全部楼层 |阅读模式
本帖最后由 wangqh1983 于 2013-10-15 20:35 编辑

现遇到的问题是在电能表显示问题, 我使用的单片机是PIC18F46k22, 电能数据二次值显示范围是0~999999999wh, long类型可以支持到,我通过打印函数可以将该数据显示,
但是要是有PT和CT变比的话,要还原一次值显示kwh,Mwh的时候数据类型就难以处理了.这个时候数据该如何处理呢? 我倒是可以将两个long打印拼成一个长的数据,可是这个数据该如何处理呢?
如果能支持long long就好了,真是头痛......

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2013-10-15 15:01:44 | 显示全部楼层
大数的四则运算么?

出0入0汤圆

 楼主| 发表于 2013-10-15 15:08:01 | 显示全部楼层
usingavr 发表于 2013-10-15 15:01
大数的四则运算么?

是的,可是这个值乘10就超过long了.

出0入0汤圆

发表于 2013-10-15 15:08:40 | 显示全部楼层
除了用汇编自己写以外没啥好办法了。

出0入0汤圆

发表于 2013-10-15 15:35:21 | 显示全部楼层
用一个数组来保存“大数”
以加法为例,低位的加完了,把进位给高位
如果是乘法,注意乘积的最大值

出0入0汤圆

 楼主| 发表于 2013-10-15 15:49:22 | 显示全部楼层
突发灵感!我想我已经找到万全之策,稍后回复......

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-10-15 15:53:32 | 显示全部楼层
usingavr 发表于 2013-10-15 15:35
用一个数组来保存“大数”
以加法为例,低位的加完了,把进位给高位
如果是乘法,注意乘积的最大值 ...

注意他是电能表,累加肯定是你说的方法,一点一点加起来,如果溢出就把高位进位。
他的问题你没看明白,累加出来的这个大数数组如何送显,不自己做一套长整形(比C编译器最长还要长)算法函数是不行的。

出0入0汤圆

发表于 2013-10-15 16:02:27 | 显示全部楼层
marx 发表于 2013-10-15 15:53
注意他是电能表,累加肯定是你说的方法,一点一点加起来,如果溢出就把高位进位。
他的问题你没看明白, ...

可以分为两个数打印啊

出0入0汤圆

发表于 2013-10-15 16:08:41 | 显示全部楼层
usingavr 发表于 2013-10-15 16:02
可以分为两个数打印啊

你如何把0x2540be3ff打印成9999999999?

出0入0汤圆

发表于 2013-10-15 16:13:46 | 显示全部楼层
marx 发表于 2013-10-15 16:08
你如何把0x2540be3ff打印成9999999999?

先实现大数运算,然后将大数除以1000000,打印,将大数模1000000,补零打印

出0入0汤圆

发表于 2013-10-15 16:16:14 | 显示全部楼层
usingavr 发表于 2013-10-15 16:13
先实现大数运算,然后将大数除以1000000,打印,将大数模1000000,补零打印

大数除以1000000的算法不要自己写吗?系统不支持的长度的整形除法难道不需要自己写么?写出来就是楼主要求的答案了。

出0入0汤圆

发表于 2013-10-15 16:21:51 | 显示全部楼层
marx 发表于 2013-10-15 16:16
大数除以1000000的算法不要自己写吗?系统不支持的长度的整形除法难道不需要自己写么?写出来就是楼主要 ...

以前做加密算法的时候用的,不保证正确性,楼主可以自己实现一下
int bigdiv_v2(bignum_store_t a[], bignum_store_t b, bignum_store_t c[], bignum_store_t *d)
{
    int len, rlen, i;

    len = a[0];
    rlen = len;
    for (i=rlen-1; i>=1; i--)
    {
        if (a == 0)
            len = i;
        else
            break;
    }

    *d = 0; // clear d
    for (i=len-1; i>=1; i--)
    {
        bignum_calc_t temp = *d;
        //bignum_store_t tsmall;
        temp  = (temp << 32) + a;
        //tsmall = (bignum_store_t)(temp - b); // this must be within bignum_store
        //temp = temp / b;
        c = (bignum_store_t)(temp / b);
        *d = (bignum_store_t)(temp % b);
    }
    if (len > 1 && c[len-1] == 0)
    {
        len--;
    }
    c[0] = len;

    printf("Big / small: ");
    for (i=len-1;i>=1;i--)
        printf("%u,",c);
    printf("\n");

    return len;
}

出0入0汤圆

 楼主| 发表于 2013-10-15 20:21:32 | 显示全部楼层
因为8位机一般不支持long long 但是都支持float 把数据转换成浮点,用浮点运算就可以了。再用浮点判断数据范围,之后把显示数据缩短到显示范围,点亮K/M,
void DisplayPrimartEnergy(void)
{
    uint8_t dot, lit = INDICATE_OFF;
    uint32_t value;
    char string[9];

    primartPosEpt = 999999900;
    primartPosEpt *= scaleVoltage;
    primartPosEpt *= scaleCurrent;
   
    if (primartPosEpt < 1000000000)
    {
        lit |= KILO_INDICATE;
        value = primartPosEpt / 10;
    }
    else
    {
        lit |= MILLION_INDICATE;
        primartPosEpt /= 10000;
        if (primartPosEpt < 100000000)
        {
            dot = 2;
            value = primartPosEpt;
        }
        else if (primartPosEpt < 1000000000)
        {
            dot = 1;
            value = primartPosEpt / 10;
        }
        else
        {
            dot = 0;
            value = primartPosEpt / 100;
        }
    }
    LED_NegativeSign(INDICATE_OFF);
    LED_IndicatorLamp(lit);
    sprintf(g_charBuffer, "%09.*lf", dot, value);
    sprintf(string, "%.4s", g_charBuffer);
    LED_DisplayString(g_displayBuffer[1], "%s", (void *) string);
    sprintf(string, "%.5s", &g_charBuffer[4]);
    LED_DisplayString(g_displayBuffer[2], "%s", (void *) string);
}

出0入0汤圆

 楼主| 发表于 2013-10-15 20:32:58 | 显示全部楼层
我这里显示范围用long就可以了,如果在一个long范围不够的情况下,可以将转换的浮点数数据处理时用除以10的N次幂,放到高long,之后将余数放到低long,就可以直接用打印函数进行打印,打印出一个组合字符串就可以了!

搞定了,谢谢各位了!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-10-15 21:18:05 | 显示全部楼层
wangqh1983 发表于 2013-10-15 20:21
因为8位机一般不支持long long 但是都支持float 把数据转换成浮点,用浮点运算就可以了。再用浮点判断数据 ...

你的做法是完全错误的,8位机浮点数一般都是32位的单精度型,只有6~7位(十进制)有效精度,无法满足你自己提出的999999999的显示要求。

出0入0汤圆

 楼主| 发表于 2013-10-16 09:06:28 | 显示全部楼层
schwarz 发表于 2013-10-15 21:18
你的做法是完全错误的,8位机浮点数一般都是32位的单精度型,只有6~7位(十进制)有效精度,无法满足你自 ...

我也发现这个问题了,把999999999赋给浮点数,后面两位的是0,要不然就进位了,变成1000000000.
这要是不行,我也没辙了.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-25 22:54

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表