Else を除算する前に単純に(max-min)<(INT_MAX/127)
乗算できる場合は
、オーバーフローや未定義の動作を回避するために操作を分解する必要があります...(max-min)*input
/127
後のケースでは、両方の乗数を 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;
bit-shifting を使用したより効率的な定式化があることはほぼ確実です>>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:
EDIT
Ahem では、私の意図は 128 で割ること、つまり >>7 であり、>>8 と同じように書きましたが、これは &0xFF ではなく &0x7F である必要があります
。 %128 コンパイラがこれらの操作を単純なビット操作に変換することを信頼できるため...
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;