Slider and ZERO question


#1

I have a very simple piece of code, that creates a slider and set’s it’s value to zero (this is the constructor of my component):

addAndMakeVisible (slider = new Slider());
slider->setRange (-1.0, 2.0, 0.1);
slider->setValue (0.0, dontSendNotification);

Now i started a timer that reads the value of the slider and prints the output to the DEBUG output like so:

void MainContentComponent::timerCallback()
{
	DBG("Slider value="+String(slider->getValue()));
	DBG(String::formatted ("Slider fromatted value=%d as float=%.8f", slider->getValue(), slider->getValue()));
	if (slider->getValue() == 0)
	{
		DBG("\tvalue is zero");
	}
	else
	{
		DBG("\tvalue is not zero");
	}
}

The output is (and it’s weird):

[debug]Slider value=5.55111512e-017
[debug]Slider fromatted value=0 as float=0.00000000
[debug]	value is not zero

Why is it NOT zero ? Should i use something else then slider->getValue() == 0 as a comparison for ZERO ?


#2

Something must be changing your slider value somewhere. If you put all this on one line you get the desired output:

[code] Slider* slider = new Slider();
slider->setRange (-1.0, 2.0, 0.1);
slider->setValue (0.0, dontSendNotification);

DBG ("Slider value = " << slider->getValue());
DBG ("Slider formatted value = " << (int) slider->getValue() << " as float = " << String (slider->getValue(), 8));

if (slider->getValue() == 0.0)
{
    DBG("\tvalue is zero");
}
else
{
    DBG("\tvalue is not zero");
}

[/code]

Remember that 0.0 is a special case for floating point numbers and usually only appears if explicitly assigned. If you’re adding or subtracting to a floating point number chances are that you’ll get somewhere close to zero for is not to make any noticeable difference but never exactly 0.0. Have a read through this article for a deeper explanation of how floating point numbers are stored.

If you just want to do something when the value is close to zero use an almostEqual type function such as this one.

/** Checks to see if two values are equal within a given precision. */ template <typename FloatingPointType> inline bool almostEqual (FloatingPointType firstValue, FloatingPointType secondValue, FloatingPointType precision = 0.00001) { if (abs (firstValue - secondValue) < precision) return true; else return false; }


#3

If i add your code in the constructor i get the same result. And no, nothing is changing the slider, i created a new Introjucer project and added a slider to the constructor, no operations are done on it (setBounds() is called in the resized() call).
But i think the problem is a compiler option, i’m using MingGW with GCC4.7.2. When compiled with default options the getValue() == 0 fails, but if i add -mfpmath=sse it works.
Without it, your code:

    addAndMakeVisible (slider = new Slider());
    slider->setRange (-1.0, 2.0, 0.1);
    slider->setValue (0.0, dontSendNotification);
    DBG ("--------------------------------------------- CONSTRUCTOR");
    DBG ("Slider value = " << slider->getValue());
    DBG ("Slider formatted value = " << (int) slider->getValue() << " as float = " << String (slider->getValue(), 8));

    if (slider->getValue() == 0)
    {
        DBG("\tvalue is zero");
    }
    else
    {
        DBG("\tvalue is not zero");
    }
    DBG ("--------------------------------------------- CONSTRUCTOR");

gives me

[debug]--------------------------------------------- CONSTRUCTOR
[debug]Slider value = 5.55111512e-017
[debug]Slider formatted value = 0 as float = 0.00000000
[debug]	value is not zero
[debug]--------------------------------------------- CONSTRUCTOR

I used the default options for GCC that Introjucer gave me, i just added -g for debugging symbols, i thought that the -march=pentium4 flag (witch is present) would cover the floating-point math


#4

Can someone help me out with that ? I get the same problem on VS2010 on Win7 x64, i created a new Introjucer audio plugin project, added the slider, set it’s bounds in resized() and started the timer, the code for the timer looks like:

void ZeroTestAudioProcessorEditor::timerCallback()
{
	const double value = slider->getValue();

	DBG("Slider value: "+String(slider->getValue())+", variable value: "+String(value)+" formatted: "+String::formatted("%d", slider->getValue()));
	
	if (slider->getValue() == 0)
	{
		DBG("\tSlider value is 0");
	}
	else
	{
		DBG("\tSlider value is not 0");
	}
	
	repaint();
}

The output is:

Slider value: 5.55111512e-017, variable value: 5.55111512e-017 formatted: 0
	Slider value is not 0

Why is it not zero ? Why is the formatted value 0 but the non-formatted one negative “very little”. Is there a compile flag i should set to get this working ?
The constructor looks like (no code in the AudioProcessor has been changed/added, no other methods in the editor have been added except for resized()):

ZeroTestAudioProcessorEditor::ZeroTestAudioProcessorEditor (ZeroTestAudioProcessor* ownerFilter)
    : AudioProcessorEditor (ownerFilter)
{
    // This is where our plugin's editor size is set.
	addAndMakeVisible (slider = new Slider());
	slider->setRange (-1, 100, 0.1);
	slider->setValue (0, dontSendNotification);
    setSize (400, 300);
	startTimer (500);
}

– Update
It looks like REAPER and the Plugin Host (from Juce sources) when loading that example plugin, make 0 actual ZERO, but when i tested it in FLStudio it’s not zero. It looks like a hosting issue, maybe something with 64/32bits (though FLStudio.exe looks like a 32bit binary just like the others)


#5

Well it looks like the method at fault is constrainedValue(). When setting slider’s proprties like so:

slider->setRange (-1.0, 100.0, 0.1);
slider->setValue (0, dontSendNotification);

The method constrainedValue() returns 5.55111512e-017 instead of 0.