Format real to byte [], NOT string

D

Dennis Myrén

Hi.

Is there a way to utilize the great primitive data type
formatting routines available in .NET without working with
strings?

I want a byte [] directly rather than a string.
I think it is unfortunate that i have to walk via System.String to do that.

For instance, from an integer of value 123, i want:
new byte [3] { ASCII.Digit1, ASCII.Digit2, ASCII.Digit3 }

I have managed to write my own formatting routines for
integer types ushort, short, uint, int, ulong and long
that create a byte array directly without walking via string.

But the floating point formatting routines is kind of complicated,
i rather not writing them if someone else has already done it and are
willing to share
that or (but i have never seen anything like it) if the .NET framework
provides something
for this. I am looking to be as efficient as possible
(that is why i am interested in this in the first place).

By now, i have to do a Math.Round, then format the number into string(also
passing a NumberFormatInfo),
then create a byte array from that. It is just too much overhead.

I always want the real numbers formatted with a maximum precision of 5
decimals,
using '.' for number group separator.
For instance, from a float of value 3.14F, i want:
new byte [4] { ASCII.Digit3, ASCII.Dot, ASCII.Digit1, ASCII.Digit4 };


If there is nothing like it, do you know where to find information
about the internal bit-level RAM representation of System.Single/Double?


How can i solve this?
 
J

Jon Skeet [C# MVP]

Dennis Myrén said:
Is there a way to utilize the great primitive data type
formatting routines available in .NET without working with
strings?

I want a byte [] directly rather than a string.
I think it is unfortunate that i have to walk via System.String to do that.

Why? Do you have any evidence that it's actually hurting your
performance significantly? I'd try things the simple way and then see
whether the performance is good enough before rushing to write custom
formatting code.
For instance, from an integer of value 123, i want:
new byte [3] { ASCII.Digit1, ASCII.Digit2, ASCII.Digit3 }

I don't know of any way of doing that, no.

If there is nothing like it, do you know where to find information
about the internal bit-level RAM representation of System.Single/Double?

They're IEEE 754 numbers, so look for specs for that - there are plenty
around.

You could look at my DoubleConverter code referenced on
http://www.pobox.com/~skeet/csharp/floatingpoint.html for some ideas,
too, but that's not really designed for efficiency particularly.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

For instance, from an integer of value 123, i want:
new byte [3] { ASCII.Digit1, ASCII.Digit2, ASCII.Digit3 }

I think you have an understanding problem about the types, I will try to
explain the differences but I think it's not an easy going.

An integer is just a set of bits , you can interprete it in different ways,
if you use decimal you may see it as 123 , if you use hex you get 7B, the
thing is that THE SAME sequence of bits is interpreted in different ways
(maybe the "interpreted" word is not the best , printed is more accurate ).
Also remember that 123 as an integer is a whole thing, is not a thing
composed of three subcomponents ( 1 , 2, 3 ) that you can access it
independently.

This is where the conversion takes part, you want to CHANGE the way an
integer is represented, hence you have to make some operations, you can have
two options:
1- Convert to a string, this work cause the string representation of 123 is
composed of 3 "subcomponents" that you can access independently : '1' , '2',
'3'
2- Make the conversion using numeric method:
digit1 = 123/100

...


A similar thing with the double


Cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation




I have managed to write my own formatting routines for
integer types ushort, short, uint, int, ulong and long
that create a byte array directly without walking via string.

But the floating point formatting routines is kind of complicated,
i rather not writing them if someone else has already done it and are
willing to share
that or (but i have never seen anything like it) if the .NET framework
provides something
for this. I am looking to be as efficient as possible
(that is why i am interested in this in the first place).

By now, i have to do a Math.Round, then format the number into string(also
passing a NumberFormatInfo),
then create a byte array from that. It is just too much overhead.

I always want the real numbers formatted with a maximum precision of 5
decimals,
using '.' for number group separator.
For instance, from a float of value 3.14F, i want:
new byte [4] { ASCII.Digit3, ASCII.Dot, ASCII.Digit1, ASCII.Digit4 };


If there is nothing like it, do you know where to find information
about the internal bit-level RAM representation of System.Single/Double?


How can i solve this?
 
D

Dennis Myrén

Hi, and thanks for reply.

Yes, i know integers is not stored the way i want them formatted in memory.
But i have no problem with formatting integers(all types) to byte arrays,
it was just an example to let you know what i wanted,
what i am really interested in is a way of formatting real numbers
without creating one or more System.String instance first.

If you are interested, i will include an example of the function i came up
with for formatting a 32-bit integer and writing directly to a stream at the
end of this message.

However, System.Single/Double is not that easy at all, at least
not until i have learnt how it is internally stored.
I have found some Microsoft code that formats floating point numbers
into byte array, but have not got it working properly.
I have not found much more than that.

Here is an example of writing Int32 formatted directly to stream, no string
is created.
<Int32ToByteArrayExample>
public override void Write ( int value )
{
bool negative = 0x0 > value;
byte i = 0xB;
byte [] buf = new byte ;
if (negative)
if (-10 >= value)
{
buf [-- i] = ByteSequences.base10 [-(value % 0xA)];
value /= -10;
}
else
value = -value;
while (0xA <= value)
{
buf [-- i] = ByteSequences.base10 [value % 0xA];
value /= 0xA;
}
buf [-- i] = ByteSequences.base10 [value];
if (negative)
buf [-- i] = ASCII.Minus;
base.Write(buf, i, 0xB - i);
}
</Int32ToByteArrayExample>



--
Regards,
Dennis JD Myrén
Oslo Kodebureau
Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

For instance, from an integer of value 123, i want:
new byte [3] { ASCII.Digit1, ASCII.Digit2, ASCII.Digit3 }

I think you have an understanding problem about the types, I will try to
explain the differences but I think it's not an easy going.

An integer is just a set of bits , you can interprete it in different
ways,
if you use decimal you may see it as 123 , if you use hex you get 7B, the
thing is that THE SAME sequence of bits is interpreted in different ways
(maybe the "interpreted" word is not the best , printed is more
accurate ).
Also remember that 123 as an integer is a whole thing, is not a thing
composed of three subcomponents ( 1 , 2, 3 ) that you can access it
independently.

This is where the conversion takes part, you want to CHANGE the way an
integer is represented, hence you have to make some operations, you can
have
two options:
1- Convert to a string, this work cause the string representation of 123
is
composed of 3 "subcomponents" that you can access independently : '1' ,
'2',
'3'
2- Make the conversion using numeric method:
digit1 = 123/100

...


A similar thing with the double


Cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation




I have managed to write my own formatting routines for
integer types ushort, short, uint, int, ulong and long
that create a byte array directly without walking via string.

But the floating point formatting routines is kind of complicated,
i rather not writing them if someone else has already done it and are
willing to share
that or (but i have never seen anything like it) if the .NET framework
provides something
for this. I am looking to be as efficient as possible
(that is why i am interested in this in the first place).

By now, i have to do a Math.Round, then format the number into
string(also
passing a NumberFormatInfo),
then create a byte array from that. It is just too much overhead.

I always want the real numbers formatted with a maximum precision of 5
decimals,
using '.' for number group separator.
For instance, from a float of value 3.14F, i want:
new byte [4] { ASCII.Digit3, ASCII.Dot, ASCII.Digit1, ASCII.Digit4 };


If there is nothing like it, do you know where to find information
about the internal bit-level RAM representation of System.Single/Double?


How can i solve this?
 
D

Dennis Myrén

Thanks Jon.

I have looked at your DoubleConverter, which is really cool, i just have to
break it down to pieces to understand all the code.


--
Regards,
Dennis JD Myrén
Oslo Kodebureau
Dennis Myrén said:
Is there a way to utilize the great primitive data type
formatting routines available in .NET without working with
strings?

I want a byte [] directly rather than a string.
I think it is unfortunate that i have to walk via System.String to do
that.

Why? Do you have any evidence that it's actually hurting your
performance significantly? I'd try things the simple way and then see
whether the performance is good enough before rushing to write custom
formatting code.
For instance, from an integer of value 123, i want:
new byte [3] { ASCII.Digit1, ASCII.Digit2, ASCII.Digit3 }

I don't know of any way of doing that, no.

If there is nothing like it, do you know where to find information
about the internal bit-level RAM representation of System.Single/Double?

They're IEEE 754 numbers, so look for specs for that - there are plenty
around.

You could look at my DoubleConverter code referenced on
http://www.pobox.com/~skeet/csharp/floatingpoint.html for some ideas,
too, but that's not really designed for efficiency particularly.
 

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

Top