Jump to page: 1 2
Thread overview
Possible unsigned float type?
Nov 01, 2005
Garett Bass
Nov 01, 2005
Regan Heath
Nov 02, 2005
Don Clugston
Nov 02, 2005
kris
Nov 02, 2005
Garett Bass
Nov 02, 2005
Garett Bass
Nov 03, 2005
Garett Bass
Nov 03, 2005
Don Clugston
Nov 03, 2005
Oskar Linde
Nov 03, 2005
Georg Wrede
Nov 03, 2005
Garett Bass
Nov 03, 2005
Sean Kelly
Nov 04, 2005
Garett Bass
Nov 03, 2005
Lionello Lunesu
November 01, 2005
I would really like to have an unsigned float type for a project I'm working on.  Some measurements, such as width, height, just don't make any sense if they are allowed to be negative, and no one wants to write checks or clamps all over the place to deal with it.

In C++ I created a set of pseudonumeric classes that overloaded all of the math operators to allow me to easily perform the usual routines on my "unsigned float" values.  However, such classes never really interact quite right with native types, and I ended up using operator ( ) to quickly retrieve the actual float value when I needed to mix it up with built-in data types.

Overall, this is sloppy and unfortunate.  Is it possible to create pseudonumeric classes in D that interact normally with other built-ins without casting or ( )'ing all the time?  Would it be difficult to incorporate an unsigned float built-in type?

Regards,
Garett


November 01, 2005
On Mon, 31 Oct 2005 23:02:53 -0600, Garett Bass <garettbass@studiotekne.com> wrote:
> I would really like to have an unsigned float type for a project I'm working
> on.  Some measurements, such as width, height, just don't make any sense if
> they are allowed to be negative, and no one wants to write checks or clamps
> all over the place to deal with it.
>
> In C++ I created a set of pseudonumeric classes that overloaded all of the
> math operators to allow me to easily perform the usual routines on my
> "unsigned float" values.  However, such classes never really interact quite
> right with native types, and I ended up using operator ( ) to quickly
> retrieve the actual float value when I needed to mix it up with built-in
> data types.
>
> Overall, this is sloppy and unfortunate.  Is it possible to create
> pseudonumeric classes in D that interact normally with other built-ins
> without casting or ( )'ing all the time?  Would it be difficult to
> incorporate an unsigned float built-in type?

A while back Arcane Jill wrote a big integer class which had similar problems. Her work can be found here:
  http://svn.dsource.org/projects/deimos/trunk/etc/

Might be useful/interesting maybe.

Regan

November 01, 2005
Garett Bass wrote:
> I would really like to have an unsigned float type for a project I'm working on.  Some measurements, such as width, height, just don't make any sense if they are allowed to be negative, and no one wants to write checks or clamps all over the place to deal with it.

IMHO even if you could use unsigned types, you should always explicitly check all input values. Is it better to let variables overflow? If you don't need more than 80 bits of precision, it might be too heavy a choice to use a bigint-library. An alternative would be to create a lightweight float class of your own. D doesn't support assignment overloading, for a good reason though :)
November 02, 2005
I'd like to challenge the underlying concept here.

You do *not* want an "unsigned float". You want a "positive float".
These two concepts are fundamentally different.
Similarly, I often see code that uses 'unsigned int' or 'uint' when a positive int is desired.

An unsigned int is not a positive int. It's an integer with no sign.
I can think of two legitimate applications:
(a) as the lower-order bits in a multi-byte integer. Note that there
 really is no sign. It's not an integer, just part of one.
(b) When you need to squeeze an extra bit of resolution into an int/short/etc. This was very common in the 8-bit and 16-bit days,
rarely necessary any more except for cases like size_t.

positive int: range from 0..int.max
unsigned int: range from 0..2*int.max.

From the CPU's point of view, the difference is evident when multiplying.

Neither of this cases apply to floats.

Using a uint for a value which is only ever in the range 0..int.max is IMHO an abuse of the 'unsigned' concept. Especially since the only thing
the compiler does to enforce it is to prevent a direct assignment from a literal. Unfortunately, it's an extremely common abuse, with the primary effect of causing 'unsigned/signed mismatch' warning in C-style languages.

So, what do we really want?
In some of the Pascal-like languages, you can specify a range for an integer as being (say) -2 .. 56.
I think that what you really want is some way of defining a
type (eg PositiveDouble) which is identical to the built-in type (double) in Release mode, but at debugging includes a user-specified
class invariant. In this case
assert(isnan(this) || this>=0.0);

This would be far more powerful than the Pascal range concept, because you could
limit it to (say) positive ints, or prime numbers, ...

-Don.

Garett Bass wrote:
> I would really like to have an unsigned float type for a project I'm working on.  Some measurements, such as width, height, just don't make any sense if they are allowed to be negative, and no one wants to write checks or clamps all over the place to deal with it.
> 
> In C++ I created a set of pseudonumeric classes that overloaded all of the math operators to allow me to easily perform the usual routines on my "unsigned float" values.  However, such classes never really interact quite right with native types, and I ended up using operator ( ) to quickly retrieve the actual float value when I needed to mix it up with built-in data types.
> 
> Overall, this is sloppy and unfortunate.  Is it possible to create pseudonumeric classes in D that interact normally with other built-ins without casting or ( )'ing all the time?  Would it be difficult to incorporate an unsigned float built-in type?
> 
> Regards,
> Garett 
> 
> 
November 02, 2005
Right on.


Don Clugston wrote:
> I'd like to challenge the underlying concept here.
> 
> You do *not* want an "unsigned float". You want a "positive float".
> These two concepts are fundamentally different.
> Similarly, I often see code that uses 'unsigned int' or 'uint' when a positive int is desired.
> 
> An unsigned int is not a positive int. It's an integer with no sign.
> I can think of two legitimate applications:
> (a) as the lower-order bits in a multi-byte integer. Note that there
>  really is no sign. It's not an integer, just part of one.
> (b) When you need to squeeze an extra bit of resolution into an int/short/etc. This was very common in the 8-bit and 16-bit days,
> rarely necessary any more except for cases like size_t.
> 
> positive int: range from 0..int.max
> unsigned int: range from 0..2*int.max.
> 
>  From the CPU's point of view, the difference is evident when multiplying.
> 
> Neither of this cases apply to floats.
> 
> Using a uint for a value which is only ever in the range 0..int.max is IMHO an abuse of the 'unsigned' concept. Especially since the only thing
> the compiler does to enforce it is to prevent a direct assignment from a literal. Unfortunately, it's an extremely common abuse, with the primary effect of causing 'unsigned/signed mismatch' warning in C-style languages.
> 
> So, what do we really want?
> In some of the Pascal-like languages, you can specify a range for an integer as being (say) -2 .. 56.
> I think that what you really want is some way of defining a
> type (eg PositiveDouble) which is identical to the built-in type (double) in Release mode, but at debugging includes a user-specified
> class invariant. In this case
> assert(isnan(this) || this>=0.0);
> 
> This would be far more powerful than the Pascal range concept, because you could
> limit it to (say) positive ints, or prime numbers, ...
> 
> -Don.
> 
> Garett Bass wrote:
> 
>> I would really like to have an unsigned float type for a project I'm working on.  Some measurements, such as width, height, just don't make any sense if they are allowed to be negative, and no one wants to write checks or clamps all over the place to deal with it.
>>
>> In C++ I created a set of pseudonumeric classes that overloaded all of the math operators to allow me to easily perform the usual routines on my "unsigned float" values.  However, such classes never really interact quite right with native types, and I ended up using operator ( ) to quickly retrieve the actual float value when I needed to mix it up with built-in data types.
>>
>> Overall, this is sloppy and unfortunate.  Is it possible to create pseudonumeric classes in D that interact normally with other built-ins without casting or ( )'ing all the time?  Would it be difficult to incorporate an unsigned float built-in type?
>>
>> Regards,
>> Garett
>>
November 02, 2005
I beg to differ, I do not want a "positive float".  I want to represent an absolute floating point value, in the range [0..float.max].  It is my understanding that zero is neither a positive nor negative value.  So, if you disagree with the application of the commonly used term "unsigned" to this case, then I should perhaps be requesting a "non-negative float" ;)

However, unsigned float does seem an appropriate name as it would be the floating-point equivalent of an unsigned int.

Regards,
Garett


November 02, 2005
To clarify, I'm suggesting an IEEE floating point value where the sign bit is always guaranteed positive, hence float.max, not 2 * float.max, but I still argue that zero is a non-positive value, regardless of the sign bit representation.

"Garett Bass" <garettbass@studiotekne.com> wrote in message news:dkb7g9$et6$1@digitaldaemon.com...
>I beg to differ, I do not want a "positive float".  I want to represent an absolute floating point value, in the range [0..float.max].  It is my understanding that zero is neither a positive nor negative value.  So, if you disagree with the application of the commonly used term "unsigned" to this case, then I should perhaps be requesting a "non-negative float" ;)
>
> However, unsigned float does seem an appropriate name as it would be the floating-point equivalent of an unsigned int.
>
> Regards,
> Garett
> 


November 02, 2005
Garett Bass wrote:
> To clarify, I'm suggesting an IEEE floating point value where the sign bit is always guaranteed positive, hence float.max, not 2 * float.max, but I still argue that zero is a non-positive value, regardless of the sign bit representation.
> 
> "Garett Bass" <garettbass@studiotekne.com> wrote in message news:dkb7g9$et6$1@digitaldaemon.com...
> 
>>I beg to differ, I do not want a "positive float".  I want to represent an absolute floating point value, in the range [0..float.max].  It is my understanding that zero is neither a positive nor negative value.  So, if you disagree with the application of the commonly used term "unsigned" to this case, then I should perhaps be requesting a "non-negative float" ;)
>>
>>However, unsigned float does seem an appropriate name as it would be the floating-point equivalent of an unsigned int.
>>
>>Regards,
>>Garett
>>
> 
> 
> 
In mathematics, the signum has three different values [1]. Surely you do understand that one sign bit can represent only two states and two bits have one state too much. Therefore we have negative and positive values of 0 (two's complement actually has only positive 0).

Please explain, what should happen if I would like to do the following:

  ufloat a = 0;   // ufloat = the new "unsigned float" type

  a--;            // what happens now?
  a = ufloat.max;
  a++;            // what about now?

If you're building a purely mathematical application, why don't you just build a custom class for numerical values? It's easy to define arbitrary value ranges using the class invariant.


[1] http://en.wikipedia.org/wiki/Sign_function
November 03, 2005
OK, perhaps there is less ambiguous word than 'positive'.
Although in IEEE, zero does have a sign. So you want a type where

signbit(x)==0 for all x.
(which is not the same as x >0, because +0.0 is not >0).

But a variable of this type most definitely has a sign; it always lies on the real number line in the range [0.. infinity].

This is not true for unsigned ints. An unsigned int genuinely has no sign. When you use uint, you are saying,
"The bit representation of this number has no way of expressing the sign. I'm taking care of the sign manually in some other way."

It's not the same as saying, "this number is always >=0".
An unsigned number can just as easily represent a number which you know
is always <=0, and where you need the extra bit of resolution.
Or it can be part of a bigint number, where the sign bit is stored somewhere else.

Unfortunately, it's extremely common to confuse "no sign" with ">=0".

Again, I really think it would be more useful to be able to apply class invariants to built-in types. Then, you could call it "PositiveReal", "NonNegativeReal", "ufloat", or anything else.

Maybe with an extension to the typedef syntax; something like:

typedef real invariant { assert(signbit(this)==0); }  NonNegativeReal;

typedef int invariant { assert(this&1==1); } OddInteger;

because I really think your request is a specific instance of a more general requirement.


Garett Bass wrote:
> I beg to differ, I do not want a "positive float".  I want to represent an absolute floating point value, in the range [0..float.max].  It is my understanding that zero is neither a positive nor negative value.  So, if you disagree with the application of the commonly used term "unsigned" to this case, then I should perhaps be requesting a "non-negative float" ;)
> 
> However, unsigned float does seem an appropriate name as it would be the floating-point equivalent of an unsigned int.

> 
> Regards,
> Garett 
> 
> 
November 03, 2005
> From the CPU's point of view, the difference is evident when multiplying.

There are more operations that are different for unsigned and signed integers: shifting (sign extension) and comparisons (less than <-> smaller than).

I use "uint" everywhere in my array classes. Not for the larger range (although one could claim this is necessary for an array class: it should be able to span all memory and therefor needs all bits), but for easier range checking:

T& operator [] ( uint i ) { assert(i<length); return ptr[i]; }

whereas with an signed int you'd need two comparisons:

T& operator [] ( int i ) { assert(i>=0 && i<length); return ptr[i]; }

This is just one example where I definately don't want just a restricted integer: I don't need the full range, but since negative values make no sense, and the generated 'unsigned' code is shorter, I use an unsigned integer.

Because the FPU has no similar concept, like unsigned float, I do think it should not be a built-in type, but some class with overriden operators.

L.


« First   ‹ Prev
1 2