PIC 18F2431上的单位转换

时间:2014-05-23 16:03:49

标签: optimization floating-point long-integer

根据每平方英寸压力(PSI)和兆帕斯卡(MPa),我有以下转换:

psi = MPa*1.45038;

我需要将转换后的最低值设为1 PSI。我正在寻找的一个例子是:

psi = ((long)MPa*145)/100

有没有使用floatlong来优化内存和速度?我将在微控制器(PIC 18F2431)上实现这种转换。

2 个答案:

答案 0 :(得分:1)

你应该用2的幂除以。根据{{​​1}}的类型及其最大值,您可以选择不同的分母来满足您的需求。如果乘法不会溢出,则无需转换为更宽的类型

如果MPa属于MPa类型,则可以int16_t(95052 /65536≈1.450378)

如果例如MPa不大于1024或2 10 那么你可以将它与2 21 相乘而不会溢出,因此你可以增加分子/分母以获得更多精度

psi = MPa*95052/(1 << 16);

修改

如果编译器的int类型是16位,那么95052将是psi = MPa*3041667/(1 << 21); 类型,因此MPa将被提升为long。如果您不想处理int32_t并且不需要太高的精确度,那么您可以使用long / int

因为MPa不大于20所以你可以将它除以2048,这是2的最大幂,小于或等于2 16 / 20.

int16_t

请注意,psi = MPa*2970/(1 << 11); *具有相同的优先级,因此它将从左到右进行评估,上面的等式将与

相同
/

<强> EDIT2:

不幸的是,如果MPa的范围是[0,2000],那么你只能将它乘以32而不会溢出16位无符号整数。您可以获得的最接近的值是psi = (MPa*2970)/2048; // = MPa*1.4501953125) ,因此如果您需要更高的精度,除了使用46/32 = 1.4375

之外别无他法

答案 1 :(得分:0)

  1. 计算最大N,以便MPa*1.45038*2^N < 2^32

  2. 计算K = floor(1.45038*2^N)一次

  3. 的常量值
  4. psi = (MPa*K)>>N

  5. 的每个值计算MPa的值

    0 <= MPa <= 2000起,您必须选择N2000*1.45038*2^N < 2^32

    • 2^N < 2^32/(2000*1.45038)
    • N < log(2^32/(2000*1.45038))
    • N < 20.497
    • N = 20

    因此,K = floor(1.45038*2^N) = floor(1.45038*2^20) = 1520833

    因此,对于MPa的每个值,您都可以计算psi = (MPa*1520833)>>20

    您需要确保MPaunsigned(或相应地投射)。

    使用此方法可以避免浮点运算。


    为了更准确,您可以使用round代替floor,为您提供K = 1520834

    在这种特定情况下,它会很好,因为2000*1520834小于2^32

    但是使用不同的最大值MPa或不同的转化标量,它可能不会。

    在任何情况下,psi的每个值K的结果差异都是可以忽略的。


    顺便说一句,如果您不介意额外的内存,那么您可以使用查找表:

    • 添加预先计算的全局变量const unsigned short lut[2001] = {...}
    • 对于MPa的每个值,请计算psi = lut[MPa]而不是psi = (MPa*K)>>N
    • 因此,您的计划将执行mul操作,而不是shift + load次操作

    但请注意,这在运行时性能方面是否更有效取决于几个因素,例如您在其中分配查找表的内存段的可访问性,处理器的体系结构手,运行时缓存启发式等。

    因此,您需要在程序中应用一些分析,以确定哪种方法更好。