0

How can I convert two unsigned integers that represent the digit and decimal part of a float, into one float.

I know there are a few ways todo this, like converting the decimal component into a float and multiplying it to get a decimal and added it to the digit, but that does not seem optimal.

I'm looking for the optimal way todo this.

/*
 * Get Current Temp in Celecius.
 */
void  GetTemp(){


    int8_t digit = 0;      // Digit Part of Temp
    uint16_t decimal = 0;  // Decimal Part of Temp

    // define variable that will hold temperature digit and decimal part
    therm_read_temperature(&temperature, &decimal); //Gets the current temp and sets the variables to the value

}

I want to take the Digit and Decimal parts and convert them to a float type, such that it looks like digit.decimal .

It might look like this in end, but I want to find the MOST optimal solution.

/*
 * Get Current Temp in Celecius.
 */
float GetTemp(){


    int8_t digit = 0;      // Digit Part of Temp
    uint16_t decimal = 0;  // Decimal Part of Temp

    // define variable that will hold temperature digit and decimal part
    therm_read_temperature(&temperature, &decimal); //Gets the current temp and sets the variables to the value

    float temp = SomeFunction(digit, decimal);  //This could be a expression also. 

    return temp;

}

////UPDATE/// - July 5th

I was able to get the source code instead of leveraging just the library. I posted it in this GIST DS12B20.c.

    temperature[0]=therm_read_byte();
    temperature[1]=therm_read_byte();
    therm_reset();

    //Store temperature integer digits and decimal digits
    digit=temperature[0]>>4;
    digit|=(temperature[1]&0x7)<<4;
    //Store decimal digits
    decimal=temperature[0]&0xf;
    decimal*=THERM_DECIMAL_STEPS_12BIT;

    *digit_part = digit;
    *decimal_part = decimal;

Although the function will not force us to return separate parts as digit and decimal, reading from the temperature sensor seems to require this (unless i'm missing something and it can be retrieved as a float).

I think the original question still stands as what is the optimal way to make this into a float in C (this is for use with AVR and an 8bit microprocessor, making optimization key) using the two parts or to be able to retrieve it directly as a float.

DogEatDog
  • 2,899
  • 2
  • 36
  • 65
  • 2
    when you say "decimal" do you mean "number of tenths", "number of hundredths", "number of thousandths", i.e. if the digit value is 1 and the decimal value is 1, is the answer "1.1", "1.01", "1.001", ??? – franji1 May 13 '12 at 21:43
  • DogEatDog, if you're still around: Were you going to let us know exactly what the two values provided by `therm_read_temperature` are supposed to be, as requested (implicitly) by franji1's question above and (explicitly) in my answer? Or have you found a solution, or given up on this, or what? – Gareth McCaughan Jun 10 '12 at 01:33
  • I apologize for the slow response. I was able to get the library source code and am not longer forced to return to parts into two variables. I posted it in a gist [ds12b20](https://gist.github.com/3057888). Is there an optimal way to combine this as seen in therm_read_temperature? (I will update question. ) – DogEatDog Jul 06 '12 at 03:29

2 Answers2

2

What you are really running into is using fixed-point numbers. These can be represented in two ways: either as a single integer with a known magnitude or multiplier (ie. "tenths", "hundredths", "thousandths", and so on; example: value from a digital scale in ten-thousandths of a gram, held in a 32-bit integer -- you divide by 10000 to get grams), or as two integers, with one holding the "accumulated" or "integer" value, and the other holding the "fractional" value.

Take a look at the <stdfix.h> header. This declares types and functions to hold these fixed-point numbers, and perform math with them. When adding fractional parts, for example, you have to worry about rolling into the next whole value, for which you then want to increment the accumulator of the result. By using the standard functions you can take advantage of built-in processor capabilities for fixed-point math, such as those present in the AVR, PIC and MPS430 microcontrollers. Perfect for temperature sensors, GPS receivers, scales (balances), and other sensors that have rational numbers but only integer registers or arithmetic.

Here is an article about it: "Fixed Point Extensions to the C Programming Language", https://sestevenson.wordpress.com/2009/09/10/fixed-point-extensions-to-the-c-programming-language/

To quote a portion of that article:

I don’t think the extensions simplify the use of fixed types very much. The programmer still needs to know how many bits are allocated to integer and fractional parts, and how the number and positions of bits may change (during multiplication for example). What the extensions do provide is a way to access the saturation and rounding modes of the processor without writing assembly code. With this level of access, it is possible to write much more efficient C code to handle these operations.

Scott G. Hall Raleigh, NC, USA

Scott Hall
  • 36
  • 2
1

Your question contains a wrong assumption.

If you're given a decimal string and want a floating-point value, the first step should generally not be to turn it into two integers.

For instance, consider the numbers 2.1 and 2.01. What's the "decimal part" in each case? 1 and 01? Both of those equal 1. That's no good.

The only case in which this approach makes any sense is where you have a fixed number of places after the decimal point -- in which case maybe 2.1 turns into (2,1000) and 2.01 turns into (2,100), or something. But unless you've got a positive reason for doing that (which I strongly doubt) you should not do it this way.

In particular, unless therm_read_temperature is a function someone else is providing you with and whose interface you can't influence, you should make that function behave differently -- e.g., just returning a float. (If it is a function someone else is providing and whose interface you can't influence, then to get a useful answer here you'll need to tell us exactly what it's defined to do.)

Gareth McCaughan
  • 19,888
  • 1
  • 41
  • 62
  • You found my fundamental problem. I can do nothing with therm_read_temperature because it is a Legacy C library that I cannot change. Otherwise I would like to do exactly as your saying. – DogEatDog May 14 '12 at 01:00
  • @DogEatDog - I would definitely poll the data returned by therm_read_temperature as fast as possible and dump it to see the "range" of values for both values in ice water that slowly came up to ambient temperature or something. The format of the data may even be in BCD. – franji1 May 14 '12 at 03:07
  • Then, I repeat, we need to know exactly what the values returned from `therm_read_temperature` are. If the temperature (is this a real temperature, or a simulated one read from a data file, or what?) is 2.1 degrees, what are the two numbers supposed to be? Without this information there's no way to do anything. (I say "degrees" but of course nothing's been said so far about what units this temperature measurement is in.) – Gareth McCaughan May 14 '12 at 07:48
  • (question updated above). It is in celsius, although that does not matter because we still have to get the temperature. An alternate solution would be for the temperature to be returned from the sensor in Fahrenheit directly as an unsigned char. The purpose of this to make sure the temperature is in a certain range and there is a level of granularity there to monitor changes in temperature. – DogEatDog Jul 06 '12 at 03:43