有人说浮点数累计是一个工人的难题, 这个, 由于先天不足, 这个问题确实存在。但是, 为什么不避开这个问题呢? 长话短说, 思路如下:
浮点数float累计, 可以另存整取, 转化为整数累计, 一个DWORD, 可以存储40亿,大多数场合已经足够。如果遇到变态的需求,比如手要求20位有整数数字, 这个方法放后面来说:
简单来说, 就是另存整取。 如果当前累计变量大于1, 就把整数部分提取到 整数计数器中, 小数部分单独计算, 可以设置个阈值, 小数部分累计大于多少时, 提出整数,剩下的继续累积。我用c语言表示如下:
void Sum(float v, int *psumInt, float *ptail, int lv)
{
int a = floor(v); // 取出整数部分;
float t = *ptail;
*psumInt += a;
t += (v - a);
if(t > lv) //大于阈值
{
a = floor(t);
*psumInt += a;
*ptail = t - a;
}
}
上位机显示时, 可以脚本显示, 直接转换成字符串, 不丢失精度, 如果嫌麻烦, 可以plc直接求和。
2.再说变态需求, 比如20位精度,小数部分处理同上, 整数部分, 可以自己实现一个 增强型加法器,程序如下, c语言实现, 仅供参考
#include <stdio.h>
int p[5] = { 0}; //每个int存放四位十进制小数;4 * 5 = 20;
void LargeAdd(int *p, int v) //简单示意, 没考虑内存安全, 和v>MaxInt;
{
int i = 0;
p[0] += v; //低四位相加
for(i = 0; i != 4; ++i) //最高的不再进位, 默认不超过20位
{
if(p[i] >= 10000) //加法进位, 小学知识
{
p[i + 1] += p[i] / 10000; //整除
p[i] %= 10000; //求余
}
}
}
int main()
{
for(int i = 1; i <= 2000; ++i)
{
LargeAdd(p, i);
printf("%d: ", i);
for(int j = 0; j != 5; ++j)
{
printf("%04d", p[4 - j]);
}
printf("\n");
}
}
如上, 任意位数的累加都可以实现;
所以, 也许浮点数累加有问题, 但是累加绝无问题。 办法总比困难多。