2014-01-28 17 views
3

我在SDCC 2.8.0上,所以在内存和代码大小方面非常有限。说我有在0和127之间变化的输入值,我想将它扩展到20 - 100。通常情况下,我会做:希望将int整型为int整型数学

int scale(int input, int min, int max) 
{ 
// assuming max is always greater than min 
float range = (float)max - (float)min; 
int output = min + int((range/127.f) * (float)input); 
return output; 
} 

通过调用scale(64, 20, 100);我得到60,这是20之间恰好一半100.

如何在不使用浮点数的情况下做到这一点?任何移位魔法?

+0

你的整数有多大? “max - min”最高值是多少? –

+0

如果可能,请尝试使用更新的SDCC。最新版本是3.3.0和3.4.0。即将到来。自2.8.0以来,SDCC有了很大提高。 –

回答

2

如果(max-min)<(INT_MAX/127)那么你可以naivly将/127
东西之前乘(max-min)*input,你必须为了避免溢出和不确定的行为分解操作...

在后一种情况下,一个天真的可能性是通过127.

A=Q1*127+R1 
B=Q2*127+R2 
A*B = (Q1*Q2*127 + Q1*R2 + Q2*R1) * 127 + R1*R2 
(A*B)/127 = Q1*Q2*127 + Q1*R2 + Q2*R1 + (R1*R2/127) 

或用C来划分两个乘法器:

unsigned int range=max-min; 
unsigned int output = min 
    + (range/127)*(input/127)*127 
    + (range/127)*(input%127) 
    + (range%127)*(input/127) 
    + (range%127)*(input%127)/127; 

这是相当肯定有与位移>>8,编译器可能已经把它做好更有效的提法,但也许不那么好,我们可以更好地帮助他:

A=Q1*128+R1 
B= 0*128+R2 (because B<=127) 
A*B = (Q1*R2) * (127+1) + R1*R2 
(A*B)/127 = Q1*R2 + (Q1*R2 + R1*R2)/127 

,并在C:
编辑
咳咳,我的意图是通过128来划分,即>> 7,我写错>> 8相同的余数应为& 0x7F的不& 0xFF的
这当然最好少晦涩和公正写/ 128和%128因为我们可以相信,编译器把这些OPS成简单的位OPS时下...

unsigned int range=max-min; 
unsigned int high=(range/128)*input; 
unsigned int low =(range % 128)*input; 
unsigned int output = min + high + (high+low)/127; 

EDIT2
为了平衡分布的更好一点,我们可能会采用某种形式的舍入,而不是像这样截断:

unsigned int output = min + high + (high+low+63)/127; 
+0

嗯,这个工程!我采取了不同的路线,但这比我的生成方式更少。谢谢! –

+1

直接映射到规定的端点(如((x-OldLow)*(NewHigh-NewLow)/(OldHigh-OldLow)+ NewLow))并不总是很清楚是正确的。通常,这些值表示某种类的bin,在这种情况下,实际跨度不是“高 - 低”,而是“高 - 低+ BinWidth”。为此调整地图可能会提供更好的质量转换。 –

+1

@EricPostpischil是的,例如当范围= 63时,会有一个输入导致最大值,三个导致最小值。这符合原始功能,但我们可以做得更好...哦,但是当范围> 127时,您正在谈论两个垃圾箱之间的分隔...... –

相关问题