Knob value of "0" not drawing right with String (knob.getValue())

I am sure I am doing something wrong here, something I overlooked, I can’t see the it though.

This code;

    knob.setSliderStyle (Slider::SliderStyle::Rotary);
	knob.setRange (-5.0f, 5.0f, 0.1f);
	knob.setValue (0.0f);
	addAndMakeVisible (knob);

    knob.setBounds (25, 25, 300, 300);

and in paint();

	g.drawSingleLineText (String (knob.getValue ()), 170, 50, 1);

Produces this result;
Knobtest

Even if I do this before the drawtext;

knob.setValue (0.0f);

If I set the slider to a non-zero value, it draws fine.

Also if I instead set a double variable to 0.0f, and draw that variable instead of the knob value, it draws fine.

Use setNumDecimalPlacesToDisplay()

And I use that when making the knob, or make string from value?

The below worked;

g.drawSingleLineText (String (knob.getValue(), 2, false), 170, 25, 1);

That specifies number of decimal places, and sets useScientificNotation to false.

Either way it makes no sense, why the same draw and string function would display a float variable correct, but not a value from a slider, and let me repeat here that if the slider value is ANYTHING but zero, it draws fine, with only one decimal place, it’s just not smart enough to figure out what to do with a zero, or so it seems!

Nope exact same result. Seems like a bug to me.

    knob.setSliderStyle (Slider::SliderStyle::Rotary);
	knob.setRange (-5.0f, 5.0f, 0.1f);
	knob.setValue (0.0f);
	knob.setNumDecimalPlacesToDisplay (1);
	addAndMakeVisible (knob);

This is a workaround, but is totally weird that it is seems needed, and cumbersome;

knob.setNumDecimalPlacesToDisplay (1);
g.drawSingleLineText (String (knob.getValue (), knob.getNumDecimalPlacesToDisplay (), false),
                      170, 50, 1);

Where as this do NOT work;

knob.setNumDecimalPlacesToDisplay (1);
g.drawSingleLineText (String (knob.getValue ()), 170, 50, 1);

Because setNumberDecimalPlacesToDisplay just formats a Slider’s label. If you want to get a value from Slider and display it independently, you should format it independently via one of String constructors.

I should also mention if I setup my knob as this;

knob.setRange (-5.0f, 0.0f, 0.1f);
knob.setValue (0.0f);

or this;

knob.setRange (0.0f, 5.0f, 0.1f);
knob.setValue (0.0f);

both WITHOUT setNumDecimalPlaces(1), they both draw right!

The method knob.getValue() returns a double number (aka 64 bit floating point). There are numerical reasons, why in your case it is never zero, and they are related to how the range of the slider is defined.
The name “getNumberDecimalPlacesToDisplay()” gives a hint, that this only affects, how the number is displayed in the text box.
For your own drawSingleLineText, you requested the conversion of a precise double number (bear in mind, the computer never uses the decimal system (except when it needs to please you, i.e. when displaying). So you have to specify, how you want that number to be converted to a string, which you correctly did in your post above, by specifying the number of decimal places in the String constructor and the bool flag to never use the scientific notation.

Thanks, but either way the problem only occurs when the range is from negative to positive.

It just makes no sense to me, that just because the range goes from negative to positive, when I set it at exact “0.0”, like when I do with a range of for example “0 to 5”, it draws it with String() totally different!

As Daniel said: it is related how values are calculated according to a given range and interval.

The Slider uses a range. The range you provided is -5.0 to 5.0 with an interval of 0.1. This means, we have 101 discrete values:

  • max - min = 10
  • 10 steps per 1 => 100
  • the maximum included => 101

If you calculate now the middle of 101, which supposedly 0 is, you end up with
-5 + (101 * 0.1 / 2) = 5.05 - 5 = 0.05

This is, why you end up with not zero.

Now another problem: the Slider works in double precision. You forced the number -5.0 to be converted to float (-5.0f) which is then as argument implicitely converted to double.

The numeric value of -5.0 might not even exist as precise number in float, or in double, or in both.
So there is lots of room, why a float doesn’t end up with the precise number you expect it to be.

1 Like

And it is illogical and inconsistent, and should be fixed. A zero should be the exact same, and be displayed the exact same, whether my range is from -5 to 5, or -5 to 0, or 0 to 5.

Thanks and that identified my mistake, using floats as min, max, and increment.

Now the below displays fine, without SetNumDecimalPlaces or setting same in String.

knob.setRange (-5.0, 5.0, 0.1);
knob.setValue (0.0);

Still it makes no sense to me, as to why the slider even with setting values to float, does not takes the increments and values right, like so; “-5.0, -4.9, -4.8…0.0, 0.1, 0.2” and so on.

I just had to put it in a playground to see myself.
I get no rounding errors, no matter if there are even or odd numbers of steps, so my assumption above was wrong.

The error only occurs when converting the numbers to float and back. And that’s the numerical error I mentioned above, the discrete numbers in 32 bit float or 64 bit float are not the same, some of them are not convertible without rounding errors.

Yes thank you very much, I already noted this and thanked you.

Sure, was more a note to myself, that my calculation of 101 steps was humbug :slight_smile:

I forgive you :slight_smile: Reminds me I am craving for a hamburger though!

Yes, that would be a little strange and never had such a problem. I’ve just tested it and it is working as expected… But I see it’s already solved :slight_smile:
Anyway, when comes to displaying decimal places, it should be formatted separately. setDecimalPlacesToDisplay does not format the value internally.