的基本前提是:
- 鉴于binary32
float
。
- 形成组合的
whole
和派系零件hundredths
的二进制定点表示。该代码使用分别编码整个和百分之一个字段的结构。重要的是,whole
字段至少为32位。
- 左移/右移(* 2和/ 2)直到MSbit位于隐含位的位置,同时对移位进行计数。一个可靠的解决方案还会记录移出的非零位。
- 形成一个有偏指数。
- 圆形尾数和隐含位。
- 表单标志(这里没有完成)。
- 结合以上3个步骤形成答案。
- 作为子法线,infinites &非数字不会导致与
whole, hundredths
输入,生成那些float
特殊情况不在这里解决。
。
#include <assert.h>
#include <stdint.h>
#define IMPLIED_BIT 0x00800000L
typedef struct {
int_least32_t whole;
int hundreth;
} x_xx;
int_least32_t covert(int whole, int hundreth) {
assert(whole >= 0 && hundreth >= 0 && hundreth < 100);
if (whole == 0 && hundreth == 0) return 0;
x_xx x = { whole, hundreth };
int_least32_t expo = 0;
int sticky_bit = 0; // Note any 1 bits shifted out
while (x.whole >= IMPLIED_BIT * 2) {
expo++;
sticky_bit |= x.hundreth % 2;
x.hundreth /= 2;
x.hundreth += (x.whole % 2)*(100/2);
x.whole /= 2;
}
while (x.whole < IMPLIED_BIT) {
expo--;
x.hundreth *= 2;
x.whole *= 2;
x.whole += x.hundreth/100;
x.hundreth %= 100;
}
int32_t mantissa = x.whole;
// Round to nearest - ties to even
if (x.hundreth >= 100/2 && (x.hundreth > 100/2 || x.whole%2 || sticky_bit)) {
mantissa++;
}
if (mantissa >= (IMPLIED_BIT * 2)) {
mantissa /= 2;
expo++;
}
mantissa &= ~IMPLIED_BIT; // Toss MSbit as it is implied in final
expo += 24 + 126; // Bias: 24 bits + binary32 bias
expo <<= 23; // Offset
return expo | mantissa;
}
void test_covert(int whole, int hundreths) {
union {
uint32_t u32;
float f;
} u;
u.u32 = covert(whole, hundreths);
volatile float best = whole + hundreths/100.0;
printf("%10d.%02d --> %15.6e %15.6e Same:%d\n", whole, hundreths, u.f, best,
best == u.f);
}
#include <limits.h>
int main(void) {
test_covert(75, 65);
test_covert(0, 1);
test_covert(INT_MAX, 99);
return 0;
}
输出
75.65 --> 7.565000e+01 7.565000e+01 Same:1
0.01 --> 1.000000e-02 1.000000e-02 Same:1
2147483647.99 --> 2.147484e+09 2.147484e+09 Same:1
已知问题:登录不适用。
几乎所有的嵌入式编译器都内置了对IEEE浮点算法软件仿真的支持。即使是微小的8位MCU。你的目标是什么,你是否试图哄骗编译器为你做这件事?但是,您经常需要在编译器设置中明确启用此功能。 – doynax
@doynax:这种库的问题是它们往往会膨胀产生的固件。对于小型MCU来说,这可以轻松地将二进制数翻倍。 – Olaf
函数定义有问题:函数应该采用“符号,整数和百分之一”。说“分数”,只提供“65”给出分数的分子,但没有分母 - 除非当然,分母是暗示的100.否则,你如何编码'75.01'? – chux