-2

Problem

I need to multiply a number without using * or + operator or other libs, only binary logic

To multiply a number by two using the IEEE norm, you add one to the exponent, for example:

12 = 1 10000010 100000(...)

So the exponent is: 10000010 (130)

If I want to multiply it by 2, I just add 1 to it and it becomes 10000011 (131).

Question

If I get a float, how do I turn it into, binary, then IEEE norm? Example: 8.0 = 1000.0 in IEEE I need it to have only one number on the left side, so 1.000 * 2^3. Then how do I add one so I multiply it by 2?

I need to get a float, ie. 6.5

Turn it to binary 110.1

Then to IEEE 754 0 10000001 101000(...)

Extract the exponent 10000001

Add one to it 10000010

Return it to IEEE 754 0 10000010 101000(...)

Then back to float 13

Community
  • 1
  • 1
tbmsilva
  • 339
  • 1
  • 3
  • 9

3 Answers3

0

Maybe not exactly what you are looking for, but C has a library function ldexp which does exactly what you need:

double x = 6.5;
x = ldexp(x, 1); // now x is 13
anatolyg
  • 26,506
  • 9
  • 60
  • 134
0

Given that the C implementation is known to use IEEE-754 basic 32-bit binary floating-point for its float type, the following code shows how to take apart the bits that represent a float, adjust the exponent, and reassemble the bits. Only simple multiplications involving normal numbers are handled.

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>


int main(void)
{
    float f = 6.125;

    //  Copy the bits that represent the float f into a 32-bit integer.
    uint32_t u;
    assert(sizeof f == sizeof u);
    memcpy(&u, &f, sizeof u);

    //  Extract the sign, exponent, and significand fields.
    uint32_t sign        = u >> 31;
    uint32_t exponent    = (u >> 23) & 0xff;
    uint32_t significand = u & 0x7fffff;

    //  Assert the exponent field is in the normal range and will remain so.
    assert(0 < exponent && exponent < 254);

    //  Increment the exponent.
    ++exponent;

    //  Reassemble the bits and copy them back into f.
    u = sign << 31 | exponent << 23 | significand;
    memcpy(&f, &u, sizeof f);

    //  Display the result.
    printf("%g\n", f);
}
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
-1

Maybe unions is the tool you need.

    #include<iostream>

    union fb {
        float f;
        struct b_s {
            unsigned int sign :1;
            unsigned int mant :22;
            unsigned int exp :8;
        } b;

    };

    fb num;

    int main() {
        num.f = 3.1415;
        num.b.exp++;
        std::cout << num.f << std::endl;
        return 0;
    }
quinzio
  • 40
  • 7
  • Do not use bit-fields here. Bit-field location [is not defined per the C standard](https://port70.net/~nsz/c/c11/n1570.html#6.7.2.1p11): "An implementation may allocate any addressable storage unit large enough to hold a bit- field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, **whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.** ... – Andrew Henle Mar 31 '19 at 22:33
  • (cont) **The order of allocation** of bit-fields within a unit (high-order to low-order or low-order to high-order) **is implementation-defined**. The **alignment** of the addressable storage unit **is unspecified**." Bit-fields are **horribly** non-portable, and you simply can not state with any certainty at all that your `sign` bit field is anywhere near the actual sign bit of the floating point value `f`. – Andrew Henle Mar 31 '19 at 22:34
  • This is a long-standing abuse of unions and has undefined behaviour. – Lightness Races in Orbit Mar 31 '19 at 22:49
  • The knee-jerk comments have missed the critical facts that the significand field is the wrong size (should be 23, not 22) and the fields are out of order (should be sign-exponent-significand or the reverse, depending). The code only printed 6.283 because the too-short significand field compensated for the sign field being in the wrong place, leaving the exponent in the desired place. – Eric Postpischil Mar 31 '19 at 23:37
  • @LightnessRacesinOrbit: The C standard defines accessing a union member other than the last one written to reinterpret the bytes. – Eric Postpischil Mar 31 '19 at 23:38
  • @EricPostpischil Oops, thought this was a C++ question! (Probably because of the C++ in the answer) – Lightness Races in Orbit Apr 01 '19 at 00:13
  • @EricPostpischil I'm going to add, though, that [whether this is well-defined even in C is still more than a little controversial](https://stackoverflow.com/q/25664848/560648) – Lightness Races in Orbit Apr 01 '19 at 00:17
  • @LightnessRacesinOrbit: I see some discussion there about whether it is a good idea for it to be defined as it is in the C standard, but I do not see argument that it is in fact defined, although I did not read everything there. – Eric Postpischil Apr 01 '19 at 01:01
  • @EricPostpischil *the fields are out of order* The fact that they fields are defined as bit-fields means the fields are not just out of order - in general the field order is completely unknown and implementation-defined. The fields in this answer as currently posted **have no known order**. Characterizing comments as "knee jerk" when a posted answer simply can not be sufficient to answer the question is somewhat of a, well, knee-jerk response. – Andrew Henle Apr 01 '19 at 13:35
  • @AndrewHenle: Implementation-defined suffices for many people in many situations. It is quite clear the intent of the author was to create a structure containing fields matching the IEEE-754 specification, that they listed the fields out of the order required for that, and that this would cause the code not to achieve its intended purpose were it not for the second error in the width of the significand field. – Eric Postpischil Apr 01 '19 at 13:48