Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
没有浮点数C如何提高精度_C_Int_Microchip - Fatal编程技术网

没有浮点数C如何提高精度

没有浮点数C如何提高精度,c,int,microchip,C,Int,Microchip,现在我正在做以下工作: uint8_t ManualFlow = 40; // 0 -> 255 Unsigned Char uint24_t ME; // 0 -> 16777215 Unsigned Short Long ME = (uint24_t) ManualFlow*10; // Have to make this hack otherwise malfunction in calculation ME /= 6; ME *= (80 - 60); ME /=

现在我正在做以下工作:

uint8_t ManualFlow = 40; // 0 -> 255     Unsigned Char

uint24_t ME; // 0 -> 16777215 Unsigned Short Long
ME = (uint24_t) ManualFlow*10; // Have to make this hack otherwise malfunction in calculation
ME /= 6;
ME *= (80 - 60);
ME /= 100;
ME *= 414;
最终结果是:

40*10 = 400
400/6 = 66
66*20 = 1320
1320/100 = 13
13*414 = 5382
我喜欢的与此类似:

4/60 = 0,0667 * 20 * 4188 * 0,998 = 5576 (more accurate).
最重要的是,如何在不使用浮点或双精度的情况下更精确地执行此操作 不要将代码大小增加太多

问候
Sonite

您可能需要了解定点算法:

WG14最新版本ISO/IEC TR 18037:2008的技术报告18037不幸不是免费的:


您可能需要了解定点算法:

WG14最新版本ISO/IEC TR 18037:2008的技术报告18037不幸不是免费的:


将所有输入乘以例如1将所有输入乘以例如1如果您确定结果不会溢出,请在除法之前执行所有乘法:

uint24_t ME;
ME = (uint24_t)ManualFlow*10;
ME *= (80 - 60);
ME *= 414;
ME /= (6 * 14);

如果你需要更多的整数精度,但要避免浮点,请考虑使用它。

如果你确信结果不会溢出,在分区之前做所有乘法:

uint24_t ME;
ME = (uint24_t)ManualFlow*10;
ME *= (80 - 60);
ME *= 414;
ME /= (6 * 14);

如果您需要整数精度,但要避免浮点,请考虑使用。

您指的是定点运算而不是浮点运算。您始终可以将整数的大小增加到uint64\u t,然后乘以10以上,以达到所需的精度


但是,我建议使用基数为2的定点,即向左移动一定数量的位,而不是将10乘以一定的幂。它更快,也更精确。

您指的是定点运算,而不是浮点运算。您始终可以将整数的大小增加到uint64\u t,然后乘以10以上,以达到所需的精度

但是,我建议使用基数为2的定点,即向左移动一定数量的位,而不是将10乘以一定的幂。它更快,也更准确。

结论:

我最初的代码没有那么好的准确性,而且有这么大

通过这样做,我增加了38字节的代码,并获得了更好的准确性

ME = (uint24_t) ManualFlow*100;
ME /= 6;
ME *= (Port[2].AD - Port[3].AD);
ME /= 100;
ME *= 414;
ME /= 10;
通过定点运算,我获得了最好的精度,但它将代码增加到1148字节->

// Utility macros for dealing with 16:16 fixed-point numbers
#define I2X(v) ((int32_t) ((v) * 65536.0 + 0.5))    // Int to Fix32
#define X2I(v) ((int16_t) ((v) + 0x8000 >> 16))     // Fix to Int

ME = I2X(ManualFlow*10); //400 * 65536.0 + 0.5 =   26214400
ME = I2X(ME/6); // 26214400 / 6 = 4369066
ME = I2X(ME * 20); // = 87381320
ME = I2X(ME / 100); // = 873813
ME = I2X(ME * 414); // 361758582
ME = X2I(ME); // 158FFF76 + 8000 >> 16 15907F76 >> 16 = 5520
希望它能帮助别人

问候 Sonite

结论:

我最初的代码没有那么好的准确性,而且有这么大

通过这样做,我增加了38字节的代码,并获得了更好的准确性

ME = (uint24_t) ManualFlow*100;
ME /= 6;
ME *= (Port[2].AD - Port[3].AD);
ME /= 100;
ME *= 414;
ME /= 10;
通过定点运算,我获得了最好的精度,但它将代码增加到1148字节->

// Utility macros for dealing with 16:16 fixed-point numbers
#define I2X(v) ((int32_t) ((v) * 65536.0 + 0.5))    // Int to Fix32
#define X2I(v) ((int16_t) ((v) + 0x8000 >> 16))     // Fix to Int

ME = I2X(ManualFlow*10); //400 * 65536.0 + 0.5 =   26214400
ME = I2X(ME/6); // 26214400 / 6 = 4369066
ME = I2X(ME * 20); // = 87381320
ME = I2X(ME / 100); // = 873813
ME = I2X(ME * 414); // 361758582
ME = X2I(ME); // 158FFF76 + 8000 >> 16 15907F76 >> 16 = 5520
希望它能帮助别人

问候
Sonite

我对原始海报的回答可能有点晚了,但对于后代来说,还应该注意的是,当速度对于小型处理器来说非常关键时,定点分割通常也可以避免。变量的除法通常是不可避免的,但几乎总是可以使用乘法和移位来代替常数的除法,这会占用许多处理器周期,特别是对于大于小型处理器数据宽度的类型。而不是

uint16_t x = somevalue;  //somevalue known to be between 0 and 65535
x /= 107;
您可以使用:

uint32_t x = somevalue;
x *= 39199;  //chosen to be 2^n/107
             //n chosen to maximum value without exceeding 65536
x >>= 22;    //n = 22 in this case

注意:这是可读性较差的代码,但如果这是一个性能至关重要的算法,则可以节省使用此优化。

我可能会晚一点回答原始海报,但对于后代来说,还应注意的是,在小处理器上速度非常关键的情况下,通常也可以避免定点分割。变量的除法通常是不可避免的,但几乎总是可以使用乘法和移位来代替常数的除法,这会占用许多处理器周期,特别是对于大于小型处理器数据宽度的类型。而不是

uint16_t x = somevalue;  //somevalue known to be between 0 and 65535
x /= 107;
您可以使用:

uint32_t x = somevalue;
x *= 39199;  //chosen to be 2^n/107
             //n chosen to maximum value without exceeding 65536
x >>= 22;    //n = 22 in this case

注意:这是可读性较差的代码,但如果这是一个性能至关重要的算法,则可以节省使用此优化。

Ah。。。很接近。这里我能得到的最大值是:400*100*414/6*14=16560000。正如你所说,你必须确保它不会溢出。我想我会去找另一个批准的。啊。。。很接近。这里我能得到的最大值是:400*100*414/6*14=16560000。正如你所说,你必须确保它不会溢出。我想我需要另一个批准。因为我有一个uint24\t,我想我只需要将ManualFlow*10增加到ManualFlow*100。这将使它更加准确。我能得到的最大值是:1000*10/6*100/100*414=689724您在那里浪费了位。。。如果有uint8和uint24,则意味着可以将uint8向左移位16位。这比乘以100要精确约600倍,而且速度更快,相较于位移位,乘法非常昂贵。因为我有一个uint24,我想我只需要将ManualFlow*10增加到ManualFlow*100。这将使它更加准确。我能得到的最大值是:1000*10/6*100/100*414=689724您在浪费位t 在这里如果有uint8和uint24,则意味着可以将uint8向左移位16位。这比乘以100的精度高约600倍,而且速度快得多,与位移位相比,乘法非常昂贵。