Toon posts:

[c] float naar char

Pagina: 1
Acties:
  • 119 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
We zitten hier met 2 man al een tijdje te werken op een probleem. Zoals de titel zegt, het omzetten van een float naar het type char.

Waarom zo'n conversie? nou we zijn hier aan het werk met een atmega32 microprocessor. Om het EEPROM te kunnen schrijven moet je karakter voor karakter de data naar het EEPROM schrijven. Dit doen we doormiddel van een array van chars.

Zou je echter een float als een array aanspreken, krijg je de binaire representatie van een float, dus een heleboel onbruikbare rommel, zoals het sign bit, de exponent en de mantissa. Wat 32 bits lang is. :9

We hebben verschillende malen de search gebruikt, maar dit heeft in niets geresulteerd. O.a functies die we geprobeerd hebben zijn:

- sprintf, maar dit gaat niet op voor floats
- g_snprintf hierbij kan de compiler de benodigde library glib.h niet vinden ;( en of dit het gewenste resultaat oplevert is bij ons ook niet bekend.
-char *fcvt();
str = fcvt(value,length,decimal,sign); heeft ook niets opgeleverd :'(

Zelf een algoritme schrijven om een float uit te gaan lezen en omrekenen naar leesbare taal lijkt mij een beetje overdreven. Er is vast wel een standaard functie voor, wij hebben deze echter nog niet kunnen vinden.

K hoop dat er iemand een oplossing weet.
:)

  • The_Ghost
  • Registratie: December 2000
  • Laatst online: 05-01-2021

The_Ghost

To beer or not to beer........

Als je de normale GlibC gebruikt zou sprintf() echt de oplossing moeten zijn.
hier een stukje uit het manual:
Floating-Point Conversions

This section discusses the conversion specifications for floating-point numbers: the %f, %e, %E, %g, and %G conversions.

The %f conversion prints its argument in fixed-point notation, producing output of the form [-]ddd.ddd, where the number of digits following the decimal point is controlled by the precision you specify.

The %e conversion prints its argument in exponential notation, producing output of the form [-]d.ddde[+|-]dd. Again, the number of digits following the decimal point is controlled by the precision. The exponent always contains at least two digits. The %E conversion is similar but the exponent is marked with the letter E instead of e.

The %g and %G conversions print the argument in the style of %e or %E (respectively) if the exponent would be less than -4 or greater than or equal to the precision; otherwise they use the %f style. A precision of 0, is taken as 1. is Trailing zeros are removed from the fractional portion of the result and a decimal-point character appears only if it is followed by a digit.

The %a and %A conversions are meant for representing floating-point numbers exactly in textual form so that they can be exchanged as texts between different programs and/or machines. The numbers are represented is the form [-]0xh.hhhp[+|-]dd. At the left of the decimal-point character exactly one digit is print. This character is only 0 if the number is denormalized. Otherwise the value is unspecified; it is implementation dependent how many bits are used. The number of hexadecimal digits on the right side of the decimal-point character is equal to the precision. If the precision is zero it is determined to be large enough to provide an exact representation of the number (or it is large enough to distinguish two adjacent values if the FLT_RADIX is not a power of 2, see Floating Point Parameters). For the %a conversion lower-case characters are used to represent the hexadecimal number and the prefix and exponent sign are printed as 0x and p respectively. Otherwise upper-case characters are used and 0X and P are used for the representation of prefix and exponent string. The exponent to the base of two is printed as a decimal number using at least one digit but at most as many digits as necessary to represent the value exactly.

If the value to be printed represents infinity or a NaN, the output is [-]inf or nan respectively if the conversion specifier is %a, %e, %f, or %g and it is [-]INF or NAN respectively if the conversion is %A, %E, or %G.

The following flags can be used to modify the behavior:

-
Left-justify the result in the field. Normally the result is right-justified.
+
Always include a plus or minus sign in the result.
If the result doesn't start with a plus or minus sign, prefix it with a space instead. Since the + flag ensures that the result includes a sign, this flag is ignored if you supply both of them.
#
Specifies that the result should always include a decimal point, even if no digits follow it. For the %g and %G conversions, this also forces trailing zeros after the decimal point to be left in place where they would otherwise be removed.
'
Separate the digits of the integer part of the result into groups as specified by the locale specified for the LC_NUMERIC category; see General Numeric. This flag is a GNU extension.
0
Pad the field with zeros instead of spaces; the zeros are placed after any sign. This flag is ignored if the - flag is also specified.

The precision specifies how many digits follow the decimal-point character for the %f, %e, and %E conversions. For these conversions, the default precision is 6. If the precision is explicitly 0, this suppresses the decimal point character entirely. For the %g and %G conversions, the precision specifies how many significant digits to print. Significant digits are the first digit before the decimal point, and all the digits after it. If the precision is 0 or not specified for %g or %G, it is treated like a value of 1. If the value being printed cannot be expressed accurately in the specified number of digits, the value is rounded to the nearest number that fits.

Without a type modifier, the floating-point conversions use an argument of type double. (By the default argument promotions, any float arguments are automatically converted to double.) The following type modifier is supported:

L
An uppercase L specifies that the argument is a long double.

Here are some examples showing how numbers print using the various floating-point conversions. All of the numbers were printed using this template string:

"|%13.4a|%13.4f|%13.4e|%13.4g|\n"


Here is the output:

| 0x0.0000p+0| 0.0000| 0.0000e+00| 0|
| 0x1.0000p-1| 0.5000| 5.0000e-01| 0.5|
| 0x1.0000p+0| 1.0000| 1.0000e+00| 1|
| -0x1.0000p+0| -1.0000| -1.0000e+00| -1|
| 0x1.9000p+6| 100.0000| 1.0000e+02| 100|
| 0x1.f400p+9| 1000.0000| 1.0000e+03| 1000|
| 0x1.3880p+13| 10000.0000| 1.0000e+04| 1e+04|
| 0x1.81c8p+13| 12345.0000| 1.2345e+04| 1.234e+04|
| 0x1.86a0p+16| 100000.0000| 1.0000e+05| 1e+05|
| 0x1.e240p+16| 123456.0000| 1.2346e+05| 1.235e+05|


Notice how the %g conversion drops trailing zeros.
en nog een stukje:
int sprintf (char *s, const char *template, ...) Function
This is like printf, except that the output is stored in the character array s instead of written to a stream. A null character is written to mark the end of the string.

The sprintf function returns the number of characters stored in the array s, not including the terminating null character.

The behavior of this function is undefined if copying takes place between objects that overlap--for example, if s is also given as an argument to be printed under control of the %s conversion. See Copying and Concatenation.

Warning: The sprintf function can be dangerous because it can potentially output more characters than can fit in the allocation size of the string s. Remember that the field width given in a conversion specification is only a minimum value.

To avoid this problem, you can use snprintf or asprintf, described below.
maar het hangt natuurlijk een beetje vast op de implementatie van sprintf() in de libraries die je ter bechikking staan....

Get your copy of the web: 'copy http://*.* a:'


  • Hermarcel
  • Registratie: April 2003
  • Niet online
Een union?

code:
1
2
3
4
union float_to_char {
    float  fFloat;
    char   cChar[sizeof(float)];
};


Edit: Ik neem tenminste aan dat je gewoon een manier zoekt om een float in de eeprom op te slaan en terug te lezen.

[ Voor 36% gewijzigd door Hermarcel op 22-11-2004 11:16 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
Snap je probleem niet. Cast de pointer (float*) naar een char * en schrijf 4 bytes weg.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

deel je float op doormiddel van een union, en schrijf de opgedeelde stukken afzonderlijk weg

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
De laatste 3 posts vergeten dat de atmega32 CPU mogelijk niet dezelfde float representatie gebruikt als de CPU van de TS. Sterker nog, die kans is meer dan 50% (LSB versus MSB, en al dan niet IEEE).

The_Ghost heeft helemaal gelijk als hij zegt dat sprintf de correcte oplossing is. Toegegeven, dan moet de atmega32 wel een scanf hebben. Dat mag je wel aannemen, als de TS om "leesbare taal".

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Hermarcel
  • Registratie: April 2003
  • Niet online
Er staat toch niet dat de data geschreven en gelezen wordt door verschillende typen cpu's? Er wordt slechts over één cpu gesproken.

Bij meerdere cpu's: sprintf() en sscanf(). Er zijn op het Internet vast wel public-domain sources voor te vinden.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
MSalters schreef op maandag 22 november 2004 @ 12:47:
De laatste 3 posts vergeten dat de atmega32 CPU mogelijk niet dezelfde float representatie gebruikt als de CPU van de TS.
Ik had aangenomen dat de float die naar EEPROM moet worden geschreven al in de mega32 aanwezig is, niet op een extern systeem.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

Topicstarter
farlane schreef op maandag 22 november 2004 @ 13:10:
[...]


Ik had aangenomen dat de float die naar EEPROM moet worden geschreven al in de mega32 aanwezig is, niet op een extern systeem.
hij is inderdaad al aanwezig.

ik ga vanavond eens even wat van de tips proberen!

k laat nog wel horen of het gelukt is :)

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Oh, dacht dat je extern een float had. Je zoekt dus simpelweg een sprintf voor de atmega32 die wel met floats werkt. Klinkt alsof je een buggy compiler hebt. GCC target de atmega32 als ik het goed zie.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

Topicstarter
MSalters schreef op maandag 22 november 2004 @ 22:08:
Oh, dacht dat je extern een float had. Je zoekt dus simpelweg een sprintf voor de atmega32 die wel met floats werkt. Klinkt alsof je een buggy compiler hebt. GCC target de atmega32 als ik het goed zie.
We hebben hier IAR embedded workbench, ik weet niet van welke compiler dit programma gebruik maakt. Maar ik denk niet dat het gcc is.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
MSalters schreef op maandag 22 november 2004 @ 22:08:
Oh, dacht dat je extern een float had. Je zoekt dus simpelweg een sprintf voor de atmega32 die wel met floats werkt. Klinkt alsof je een buggy compiler hebt. GCC target de atmega32 als ik het goed zie.
Volgens mij zoekt ie een manier om die float in EEPROM op te slaan. Hiervoor kun je nmi gewoon de bitrepresentatie nemen en die in EEPROM frotten ( waarschijnlijk per 64 bytes maar alla ).

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
Verwijderd schreef op dinsdag 23 november 2004 @ 09:06:
[...]


We hebben hier IAR embedded workbench, ik weet niet van welke compiler dit programma gebruik maakt. Maar ik denk niet dat het gcc is.
Toch wel gcc denk ik ( onze eigen software maakt daar wel gebruik van iig )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1