views:

142

answers:

4

I have a float number in c++ and the number can be in different forms, e.g. 355.5 or 9.9 (this is input from test code).

I have a function which is

float return_max(angle_set_t *angles)  
{  
    float val;  
    float max;  
    max= angles->key;  
    while( angles != NULL )  
    {  
        val= angles->key;  
        if(max<=val)  
        {  
            max=val;  
        }  
        angles = angles->right;  
    }       
    return max;
}  

max can be a float value. I want to round the value to one decimal place.

I need a general solution so it works for 355.555555 and 9.999999

float first_aset()
{
    //do somethig
    result=return_max();
    return result;
}

void main()
{
    if( first_aset(S, 357.0, 20.0 ) != 9.9 ||
        first_aset(T, 357.0, 20.0 ) != 9.9 )
    {
         printf("Error in wrap-around interval (3)\n");
         printf(" first in interval [357, 20) in S is %f, should be 9.9\n",
         first_aset(S, 357.0, 20.0 ) );
         printf(" first in interval [357, 20) in T is %f, should be 9.9\n",
         first_aset(T, 357.0, 20.0 ) );
    }
}

over here is the problem..the result is:

Error in wrap-around interval (3)

first in interval [357, 20) in S is 9.900000, should be 9.9

first in interval [357, 20) in T is 9.900000, should be 9.9

+2  A: 

Do

answer = static_cast<float>(static_cast<int>(number * 10.)) / 10.;

If instead you are just trying to display the value with that precision, try setprecision:

cout << setprecision(1) << number << endl;

In your code you're comparing a float to a double. This can only end badly (as will any floating point comparisons). It might (rarely) work if you compare to 9.9f

JoshD
This will definitely work fine for any number <= 360. However, it's not technically a "general solution" because the `number * 10` part would introduce its own rounding error when applied to very large floats (since 10 is not a power of 2).
Jon Rodriguez
but i need it for floats not doubles.
abbas
@abbas A double is a float with more storage capacity.
Jon Rodriguez
@abbas: Then replace `double` with `float`. In fact, most of the time you should be using `double` unless you intend to use *lots* of floating-point numbers.
In silico
@abbas: I've replaced the word `double` with the word `float` in my answer. That should be what you need.
JoshD
This rounds, when the example (9.99... going to 9.9) shows he wants to truncate.
Matthew Flaschen
@Jon Rodriguez: Yes, there will be some rounding errors. I'm curious, though how did you get 360 as the threshold?
JoshD
but it still doesnt work....it stil returns 9.99999999 rather than 9.9..plz help
abbas
@JoshD The OP's variable is named "angles", and he must be using degrees instead of radians given his sample values of 355.555555 and 9.999999
Jon Rodriguez
@abbas Is it possible your compiler is optimizing away the cast-within-a-cast? Instead of what JoshD wrote, try `answer = floor(number * 10. + 0.5) / 10.;`
Jon Rodriguez
im not sure...what im doing is that this function is called by another function and that function returns this value to the main function..adn then I compare it with 9.9 ...wheras my function returns 9.9999999 and the comparison fails and it ERRS.
abbas
@abbas: That's a problem with the function displaying the value, not with the rounding. 9.999999999... is equal to 10.0. @Jon: Looks to me like it's working, it rounded the value to the nearest tenth, i.e. 10.0
Ben Voigt
Also that i used the staic_cast...it gives an error
abbas
@Jon Rodriguez: He wants to truncate, so `answer = floor(number * 10.) / 10.;`
JoshD
Multiple markers at this line - expected primary-expression before ‘float’ - ‘staic_cast’ was not declared in this scope - expected unqualified-id before ‘>’ token - expected ‘;’ before ‘float’
abbas
@Ben Voigt: Yes. This is almost certainly the case.
JoshD
@abbas: That should be `static_cast` not `staic_cast`.
JoshD
Its not with diplaying the value...as the comparision fails
abbas
if( first_aset(S, 357.0, 20.0 ) != 9.9 || first_aset(T, 357.0, 20.0 ) != 9.9 ) { printf("Error in wrap-around interval (3)\n"); printf(" first in interval [357, 20) in S is %f, should be 9.9\n", first_aset(S, 357.0, 20.0 ) ); printf(" first in interval [357, 20) in T is %f, should be 9.9\n", first_aset(T, 357.0, 20.0 ) ); }
abbas
first asset() uses the method in this question and then rturns the result..to the main in which I have the above test code
abbas
@abbas: You CANNOT compare floating point numbers for equality. Floating-point numbers are inaccurate. You need to test if the absolute value of the difference is within the acceptable error margin, e.g. `if (abs(number - 9.9) < .01)`
Ben Voigt
but the problem is that only for this instance it errors ..the rest of the floating point nubers are compared just fine
abbas
@abbas Because of how floats are represented, it is dangerous to try to compare floats using == or !=. Instead of `(a != b)`, you should do `(fabs(a - b) > .0001)`. See http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
Jon Rodriguez
Furthermore, 9.9999999 with one decimal place isn't 9.9, it's 10.0. The difference between 9.99999... and 10.0 is .000...0001, or in other words, zero.
Ben Voigt
but see...I cannot change the test code...also that i need 9.9 not 10.0 or 98 which the solutions above give me...i am adding interfaces to the question..maybe that might help understanding the problem
abbas
@abbas: What's the formula that's supposed to result in 9.9? Anyway, test code that contains `if (xyz != 9.9)` is WRONG. In C++ the literal `9.9` is inexact.
Ben Voigt
there is no ofrmula..i just updated the question ..it might clear out the confusion
abbas
Plz help.......
abbas
@abbas: read the documents that Ben put in his answer. They should give you a better grounding upon which to understand the problem.
JoshD
+1  A: 
rounded = truncf(original * 10) / 10;

However, I agree with Ben that you should definitely not be checking for exact inequality. Use an epsilon if a comparison is needed.

Matthew Flaschen
Divide it by 10, too. And that will truncate rather than round... depends if that's what he wants.
JoshD
will it be divide by ten for all numbers 355.55555 as well as 9.9999999
abbas
@Josh, it's pretty clear from the example he wants to truncate.
Matthew Flaschen
@Mathew Flaschen: Yeah, I completely misread that at first. This answer works fine.
JoshD
... but truncation using floating-point is almost certainly the wrong thing to do, because it isn't idempotent
Ben Voigt
@Ben, you're right that it's not idempotent. The OP should explain further why he wants this.
Matthew Flaschen
+4  A: 

Required reading: What Every Computer Scientist Should Know About Floating-Point Arithmetic

Abbreviated explanation for the non-scientist: What Every Programmer Should Know About Floating-Point Arithmetic

Ben Voigt
+1 for the required readings. This should help clear up the confusion.
JoshD
A: 

As a side note, you seem to be building your own (intrusive) linked list. C++ already provides various containers for you such as vector and list. Also, you don't have to write a function that determines the maximum value in a sequence, just use an appropriate algorithm from the standard library.

#include <vector>
#include <algorithm>

std::vector<float> angles = {0.0, 355.5, 9.9};
float maximum = *std::maximum_element(angles.begin(), angles.end());
FredOverflow