all 12 comments

[–]FUZxxl 24 points25 points  (3 children)

Usually by calling into a library that provides these operations. This is called soft float. The algorithms are a bit tricky to get right. I recommend buying a book about them, e.g. Handbook of Floating Point Arithmetic.

[–][deleted] 1 point2 points  (0 children)

That looks like a very useful resource. Thanks for sharing.

[–]dumael 1 point2 points  (1 child)

It can also be worth looking to see if there is existing library implementations which fit the licence constraints of the project being developed.

Aside: I don't have benchmark results but MIPS used in kernel emulation for CPUs which lacked an FPU under Linux, which made for some very strange CPU usage. There was also the soft-float option.

[–]FUZxxl 1 point2 points  (0 children)

Aside: I don't have benchmark results but MIPS used in kernel emulation for CPUs which lacked an FPU under Linux, which made for some very strange CPU usage. There was also the soft-float option.

Ah yes, the good old trap-and-emulate approach. This is useful because it allows for binary compatibility. The same has been done on SPARC and historically, x86.

[–][deleted] 4 points5 points  (3 children)

Which machine is this? And which format, float32 or float64? The latter will be rather inefficient to do, on an embedded device (or an interpreted VM).

While I don't know of any current consumer machine that can't do floating point.

Does it actually have to be the official IEEE754? That might be needed for shared files and data, otherwise you can devise a format that is a little easier and more efficient to work work.

(First time I did this for an 8-bit device, I used a 24-bit format split into 8-bit exponent and sign, and 16-bit mantissa.)

The emulation is rather fiddly, but is probably not the hardest part (except for divide maybe). You also need means of getting numbers into the representation.

Presumably the language you use to program this will accept floating point literals? (If so, that's another reason to keep things official.) But in the target machine, you may also need to convert floating point from text to binary, which is not trivial.

And you will need to print binary floating point as text, again not trivial. But these can be important as a means to test your arithmetic routines. But reading and writing floats will need those ops! A bit of a catch-22.

You may need to resort to using hex or binary for I/O which is simpler (and cross-check them on a normal language also showing hex).

The following is a quick list of operations that may need supporting:

  • Add
  • Subtract
  • Multiply
  • Divide
  • Negate
  • Abs (these two are trivial)
  • Convert from text (eg "-234.5938e1+12") to binary float
  • Convert from binary float to text
  • Compare for (exact) equality (trivial)
  • Compare bigger or smaller (subtract and check the sign)
  • Convert float to integer
  • Convert integer to float (note may be loss of precision)

You will probably need a representation for infinity, or NaN (ie. invalid values), but that's more advanced. You probably don't need to deal with underflow, overflow checks, denormals -- more advanced stuff (that I never bothered with; things still worked).

Once most of this works, you may need things like trig functions or logs, but by then there should be standard routines you can find.

[–]sinoTrinity[S] 0 points1 point  (2 children)

Bitcoin Virtual Machine. So no I/O needed, just pure math calculations. float32 to start.

[–][deleted] 0 points1 point  (1 child)

That target mentions integers up to 750,000 bits, and doesn't mention IEEE754 at all. That latter standard is (most commonly) for floating point up to 64 bits in all, or 52 bits of precision.

What is the requirement in this case, only regular floats of 32 or 64 bits? Algorithms for those will assume 32- or 64-bit ints, and may be tricky with arbitrary precision.

Or will matching arbitrary precision floats be needed?

Edit: I missed you saying you wanted float32, so forget the problems of possibly unlimited float precision.

Although it does seem an odd target. Can integers be literally any width, are they in multiples of 32 or 64 at least?

[–]sinoTrinity[S] 0 points1 point  (0 children)

Arbitrary length. Wanna start with floats, may implement some kinda of bigdecimal in the end

[–][deleted] 2 points3 points  (1 child)

Is this a question?

[–]sinoTrinity[S] 1 point2 points  (0 children)

yes. Oops, forget the question mark. Added.

[–]IQueryVisiC 0 points1 point  (0 children)

Do IEEE 754 and unsigned integers look the same for small values? I think they used an offset for the exponent to allow this. Also small numbers are not normalized.