# Visual formatting of floating point variables

I recently tweaked my sunflower demo

https://beta.observablehq.com/@jbum/circles-spirals-and-sunflowers

So that the increment in the spiral animation (about 2/3rds down) displays. I used the following code.

``````    increment = {
let duration = 1000*180;
let phase = now%duration;
let degrees = phase*360/duration;
degrees = Math.floor(degrees*100)/100; // visual display to 2 decimal places
return degrees;
}
``````

Note the trick I used to force the display to 2 decimal places. Is there a better way to do this?
Iâ€™d prefer to have the actual variable unconstrained and just visually display it in %.02f formatâ€¦

This looks a little cleaner (but is still mixing up visual formatting with variable truncation).

``````      while (true) {
for (var d = 0; d < 360; d += .05) {
yield Promises.delay(25,Math.floor(d*100)/100);
}
}
}
``````

We use JavaScriptâ€™s standard number.toString in the inspector, which uses as few digits as possible to uniquely identify the value. Unfortunately that means thereâ€™s no way to control the number of displayed digits, short of rounding as you are already doing.

That said, you could implement the loop another way to avoid floating point error:

``````increment = {
while (true) {
for (var d = 0; d < 36000; d += 5) {
yield Promises.delay(25, d / 100);
}
}
}
``````

You could also have a separate cell which represents the pretty, human-readable numberâ€”but then youâ€™d see the value in two places.

``````DOM.text(increment.toFixed(2))
``````

If you want to be super fancy, and have complete control over both the value thatâ€™s exposed programmatically to the rest of your notebook separately from how it appears in the page, you can use `viewof`:

``````viewof increment = {
const pre = html`<pre class="O--inspect O--number">`;
pre.value = 0;
const interval = setInterval(() => {
pre.textContent = pre.value.toFixed(2);
pre.value += 0.05;
pre.dispatchEvent(new CustomEvent("input"));
}, 25);
yield pre;
try { yield Promises.never; }
finally { clearInterval(interval); }
}
``````

In a sense, this makes the increment cell function like an input sliderâ€”itâ€™s just that the user canâ€™t control the slider; itâ€™s only controlled programmatically by the internal timer interval. So the increment value is displayed as a PRE element (for pretty formatting), but the value exposed to the rest of the notebook is a number, pre.value. And by dispatching an input event whenever that value changes, the rest of the notebook automatically reacts.

The last part, yielding Promises.never, is so you can dispose of the interval if the cell is ever re-evaluated: when Observable re-runs the cell, it calls generator.return so you can perform any necessary cleanup.

Thatâ€™s probably a little more detail that you were expecting but I wanted to convey that you have quite a few options to tackle this problem.

1 Like

Another hacky workaround is to add some CSS (to e.g. the title cell):

``````<style>
.O--number {
display: inline-block;
max-width: 50px;
white-space: nowrap;
overflow: hidden;
}
.O--field .O--number {
display: inline;
}
</style>``````