C floating point

J

j0mbolar

C supports single precision floating point and double precision
floating point but does it support fixed floating point? i've read
that fixed floating point is more accurate than single precision
floating point when dealing with dollars and cents.
 
R

Richard Bos

C supports single precision floating point and double precision
floating point but does it support fixed floating point?

No, but it's pretty easy to simulate using integers.

Richard
 
L

Lew Pitcher

C supports single precision floating point and double precision
floating point but does it support fixed floating point?

Unfortunately,
a) "fixed" floatingpoint is a contradiction in terms. I believe you mean
"fixed point" (as opposed to "floating point" or "integer")
b) No, Standard C does not support "fixed floating point" (sic) numbers, neither
at the language level nor at the library level.
i've read
that fixed floating point is more accurate than single precision
floating point when dealing with dollars and cents.

--
Lew Pitcher
IT Consultant, Enterprise Application Architecture,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed are my own, not my employers')
 
M

Martin Dickopp

C supports single precision floating point and double precision
floating point but does it support fixed floating point?

How can the point be both fixed and floating? I'm guessing that you mean
fixed point fractional numbers, i.e. something like 123.45, where there
are always 2 decimal digits after the point.
i've read that fixed floating point is more accurate than single
precision floating point when dealing with dollars and cents.

Just represent everything as cents internally and convert it on input or
output, e.g.

int amount = 12345; /* $123.45 */
printf ("The amount is $%d.%02d\n", amount / 100, amount % 100);

(A program which uses the $ character is not strictly conforming. You
can almost certainly ignore this limitation, though.)

Martin
 
F

Francois Grieu

Martin Dickopp said:
Just represent everything as cents internally and convert it on input or
output, e.g.

int amount = 12345; /* $123.45 */
printf ("The amount is $%d.%02d\n", amount / 100, amount % 100);

This won't work portably for negative amounts, and can portably
represent amounts aonly to $327.67

Francois Grieu
 
O

osmium

j0mbolar said:
C supports single precision floating point and double precision
floating point but does it support fixed floating point? i've read
that fixed floating point is more accurate than single precision
floating point when dealing with dollars and cents.

No the language doesn't. but some compilers have BCD (binary coded decimal)
as an extension. I suspect that is what you want.
 
J

Julian V. Noble

Francois said:
This won't work portably for negative amounts, and can portably
represent amounts aonly to $327.67

Francois Grieu

IIRC, int is a signed integer, typically 16 bits. If he uses long it will be 32
bits,
so he can get numbers up to +- 21 Megabucks. That's enough for most of us unless
we are working for a major corporation or a government agency ("A billion here,
a
billion there, pretty soon it starts to add up to REAL money." -- Everett
Dirkson)

He can check it with

#include <stdio.h>

int main( void )
{
printf("The number of bytes in an int is %d.\n",sizeof(int));
printf("The number of bytes in a long int is %d.\n",sizeof(long));
return 0;
}

If more significant fixed-point figures are needed, he would have to define
quad-length signed integers. Not that hard, there are libraries. Google.

--
Julian V. Noble
Professor Emeritus of Physics
(e-mail address removed)
^^^^^^^^^^^^^^^^^^
http://galileo.phys.virginia.edu/~jvn/

"God is not willing to do everything, and thereby take away our free wiil
and that share of glory that rightfully belongs to ourselves."


-- N. Machiavelli, "The Prince".
 
P

P.J. Plauger

C supports single precision floating point and double precision
floating point but does it support fixed floating point? i've read
that fixed floating point is more accurate than single precision
floating point when dealing with dollars and cents.

Fixed-point arithmetic, with a fractional part, is not a part of
Standard C. However TR 18037 includes fixed-point arithmetic as
part of its support for Embedded C. We'll have an implementation
later this year. Don't expect it to be more accurate, in general,
than floating-point.

By "more accurate," you might mean "less surprising in its rounding
and truncation behavior." For that you need decimal arithmetic.
And the C committee has just begun work on a non-normative binding
to IEEE 754R which will include a funky kind of decimal arithmetic
that behaves a little like fixed point and a lot like floating point.
But that's years out.

Your best bet for now is to do arithmetic using integers to count
pennies.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
E

Eric Sosman

Julian V. Noble said:
He can check it [the widths of integer types] with

#include <stdio.h>

int main( void )
{
printf("The number of bytes in an int is %d.\n",sizeof(int));
printf("The number of bytes in a long int is %d.\n",sizeof(long));
return 0;
}

I have used a machine on which the output would be

The number of bytes in an int is 0.
The number of bytes in a long int is 0.

Quiz question 1: The predicted output is nonsense, so
something is clearly wrong. Is the implementation buggy,
or is there an error in the code?

Quiz question 2: How should the code be changed, either
to work around the implementation bug or to correct its
own error?

Bonus question: Once the bug is worked around or cured,
what would the output be? (Admittedly, I have not provided
enough information to answer with certainty. Still, it's
possible to make some pretty shrewd guesses.)
 
L

Lew Pitcher

Julian V. Noble said:
He can check it [the widths of integer types] with

#include <stdio.h>

int main( void )
{
printf("The number of bytes in an int is %d.\n",sizeof(int));
printf("The number of bytes in a long int is %d.\n",sizeof(long));
return 0;
}

I have used a machine on which the output would be

The number of bytes in an int is 0.
The number of bytes in a long int is 0.

Quiz question 1: The predicted output is nonsense, so
something is clearly wrong. Is the implementation buggy,
or is there an error in the code?

There is an error in the code.
Quiz question 2: How should the code be changed, either
to work around the implementation bug or to correct its
own error?

Try
printf("The number of bytes in an int is %u.\n",
(unsigned)sizeof(int));
printf("The number of bytes in a long int is %u.\n",
(unsigned)sizeof(long));
Bonus question: Once the bug is worked around or cured,
what would the output be? (Admittedly, I have not provided
enough information to answer with certainty. Still, it's
possible to make some pretty shrewd guesses.)

Hmmm. A tricky one.

My first thought is that sizeof() represents some other unsigned integral value
other than that which can be represented in an unsigned int. This means that
sizeof evaluates to either
a) an unsigned char,
b) an unsigned short,
c) an unsigned long, or
d) an unsigned long long

Since integral promotion is required in variadic functions, an unsigned char and
an unsigned short would result in the printf() function obtaining an unsigned
int, and thus would produce the proper results. Since the proper results were
not produced, this means that sizeof evaluates to either an unsigned long or an
unsigned long long. Not many platforms that I know of do this.

So, we have a platform that evaluates sizeof into a long or long long. Since
that's unusual, I'd have to say that the platform is unusual. The few unusual
conforming platforms discussed around here are mostly 'embedded' systems,
usually DSPs and the like. IIRC, the common value discussed here is 64bits for
DSP words (I know it can differ, this is what I recollect appearing /here/, in
comp.lang.c). These sorts of embedded systems seem to either use CHAR_BITS=8, or
CHAR_BITS = wordsize.

Assuming CHAR_BITS == 8, then the likely output would be
The number of bytes in an int is 8.
The number of bytes in a long int is 8.

Assuming CHAR_BITS == wordsize, then the likely output would be
The number of bytes in an int is 1.
The number of bytes in a long int is 1.


--
Lew Pitcher
IT Consultant, Enterprise Application Architecture,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed are my own, not my employers')
 
M

Malcolm

Eric Sosman said:
I have used a machine on which the output would be

The number of bytes in an int is 0.
The number of bytes in a long int is 0.

Quiz question 1: The predicted output is nonsense, so
something is clearly wrong. Is the implementation buggy,
or is there an error in the code?
I think that the wicked implementation doesn't return an integer from
sizeof(), but an unsigned long. When 0x 0000 0002 is put on the stack, the
first 16 bits are interpreted as integer 0.
Quiz question 2: How should the code be changed, either
to work around the implementation bug or to correct its
own error?
Casting the sizeof() to an int would work.
Bonus question: Once the bug is worked around or cured,
what would the output be? (Admittedly, I have not provided
enough information to answer with certainty. Still, it's
possible to make some pretty shrewd guesses.)
The number of bytes in an int is 2
The number of bytes in a long int is 4

This assumes a 4GB address space and 32 bit size_t.
 
L

Lew Pitcher

Supplemental reply below...

Julian V. Noble said:
He can check it [the widths of integer types] with

#include <stdio.h>

int main( void )
{
printf("The number of bytes in an int is %d.\n",sizeof(int));
printf("The number of bytes in a long int is %d.\n",sizeof(long));
return 0;
}
[snip]
Bonus question: Once the bug is worked around or cured,
what would the output be? (Admittedly, I have not provided
enough information to answer with certainty. Still, it's
possible to make some pretty shrewd guesses.)

Hmmm. A tricky one. [snip]
Assuming CHAR_BITS == wordsize, then the likely output would be
The number of bytes in an int is 1.
The number of bytes in a long int is 1.

OK, this isn't right either.

Assuming that CHAR_BITS == wordsize, then the original printf() statements
should have resulted in non-zero values. That is to say, if the assumption that
sizeof(char) == sizeof(int) == sizeof(long int) == sizeof(long long int)
is true, then the original statement would have resulted in a sizeof that could
be printed using a "%d" without casting. Thus, it /would/ have printed proper
results.

Since it didn't, it is unlikely that the wordsize is used for all integral
types, and the assumptions that the above answer depends on are unreliable.


--
Lew Pitcher
IT Consultant, Enterprise Application Architecture,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed are my own, not my employers')
 
M

Malcolm

j0mbolar said:
C supports single precision floating point and double precision
floating point but does it support fixed floating point?
No. One idea is to use C++ and write your own "monetary" class. If you are
really clever you can make it hyper-inflation proof (when Mr Bush's deficit
stops being funded by the Japanese you might find that prices in dollar
terms go up rather faster than expected).
Financial applications aren't usually very maths-intensive, so it probably
won't matter if the internals are rather slow.
i've read
that fixed floating point is more accurate than single precision
floating point when dealing with dollars and cents.
The problem you have is that a binary system cannot represent 1/10 or 1/100
with complete accuracy. Fixed point won't solve this problem, but using a
decimal system will.
 
J

John Cochran

SNIP...
Try
printf("The number of bytes in an int is %u.\n",
(unsigned)sizeof(int));
printf("The number of bytes in a long int is %u.\n",
(unsigned)sizeof(long));

Try instead.
printf("The number of bytes in an int is %lu.\n",
(unsigned long)sizeof(int));
printf("The number of bytes in a long int is %lu.\n",
(unsigned long)sizeof(long));
 
E

Eric Sosman

Malcolm said:
I think that the wicked implementation doesn't return an integer from
sizeof(), but an unsigned long. When 0x 0000 0002 is put on the stack, the
first 16 bits are interpreted as integer 0.
Casting the sizeof() to an int would work.
The number of bytes in an int is 2
The number of bytes in a long int is 4

This assumes a 4GB address space and 32 bit size_t.

... and the Oscar goes to Malcolm!

Actually, the two sizes were 4 and 8, respectively, rather
than 2 and 4, but that's what my parenthetical remark was about.
The important thing is that `size_t' was wider than `int', and
that the "%d" conversion picked up the wrong part of the value.
 
J

John Bode

C supports single precision floating point and double precision
floating point but does it support fixed floating point? i've read
that fixed floating point is more accurate than single precision
floating point when dealing with dollars and cents.

C doesn't have a built-in fixed data type. What you can do is use an
integral type, scaled to the smallest unit. For example, the integer
12345 may represent $123.45 (counting in cents), or $12.345 (counting
in tenths of cents), or $1.2345 (counting in hundredths of cents).

As you can see, the more precise the unit, the smaller the range. An
unsigned 16-bit integer can count from 0 to 65,535; if you're counting
in hundredths of cents, that gives you a range of $0 to $6.5535.

Alternately, you can use a struct with two members, one to keep track
of whole dollar amounts, the other to keep track of fractional
amounts:

struct val {
int dollar;
int fract;
};

so that the value $12.3456 is stored as {12, 3456}. This way you can
represent a larger range of dollars, yet still keep the precision you
want; unfortunately, the arithmetic gets a little hairier. Think
about adding the values $12.3456 and $45.82; you'll have to perform
some kind of addition on the struct values {12, 3456} and {45, 8200}.

You could also represent values as arrays of int, where each array
element corresponds to a digit (i.e., the value 123456789 is
represented as int val[]={1,2,3,4,5,6,7,8,9};); this way you can
represent values with tens or hundreds of significant digits. Again,
the math operations aren't as straightforward as for built-in types.
 
C

CBFalconer

Eric said:
Julian V. Noble said:
He can check it [the widths of integer types] with

#include <stdio.h>

int main( void )
{
printf("The number of bytes in an int is %d.\n",sizeof(int));
printf("The number of bytes in a long int is %d.\n",sizeof(long));
return 0;
}

I have used a machine on which the output would be

The number of bytes in an int is 0.
The number of bytes in a long int is 0.

Quiz question 1: The predicted output is nonsense, so
something is clearly wrong. Is the implementation buggy,
or is there an error in the code?

Error. Use "...%lu.\n", (unsigned long)sizeof(whatever));
Quiz question 2: How should the code be changed, either
to work around the implementation bug or to correct its
own error?

Bonus question: Once the bug is worked around or cured,
what would the output be? (Admittedly, I have not provided
enough information to answer with certainty. Still, it's
possible to make some pretty shrewd guesses.)

4 and 8. 2 and 4 is another possibility. The point is that size_t
must be bigger than an int.

For C99 the answers are different.
 
R

Richard Bos

Try instead.
printf("The number of bytes in an int is %lu.\n",
(unsigned long)sizeof(int));
printf("The number of bytes in a long int is %lu.\n",
(unsigned long)sizeof(long));

Not likely to be necessary; I've never seen a system with larger than
8-byte ints, let alone larger than 32767-byte ints!

Richard
 
C

CBFalconer

Richard said:
Not likely to be necessary; I've never seen a system with larger
than 8-byte ints, let alone larger than 32767-byte ints!

You miss the point. sizeof creates something of type size_t.
This may be significantly larger than an int, so lying to the
compiler about the parameter supplied to a variadic function
results in UB.
 
M

Martin Dickopp

CBFalconer said:
You miss the point. sizeof creates something of type size_t.
This may be significantly larger than an int,

The range of `size_t' may be significantly larger than the range of
`int', but that doesn't matter. As long as the /value/ returned by
`sizeof (int)' or `sizeof (long)' is guaranteed to fit in an `unsigned
int' (i.e. it is less than 32768), the cast to `unsigned int' is safe.
so lying to the compiler about the parameter supplied to a variadic
function results in UB.

Unless I'm missing something, this is not an issue here. Both variants
use %-specifications which match the argument.

Martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top