0

Consider next code:

#include <cmath>
unsigned int nump=12u;
auto inner=2.5;
auto outer=6.0;
auto single=2*3.14159265359/nump;
auto avg=0.5*inner+0.5*outer;
for (auto i=0u;i<nump;++i){
    auto theta=i*single;
    auto px=avg*sin(theta);
    auto py=avg*cos(theta);
    auto tw=17.;
    int v1=std::round(1+px-tw/2.0);
    int v2=std::round(2+py-tw/2.0);
    std::cout<<"#"<<i<<":"<<v1<<";"<<v2<<std::endl;
}

it produces output like this:

#0:-8;-2  
#1:-5;-3  
#2:-4;-4  
#3:-3;-7  
#4:-4;-9  
#5:-5;-10  
#6:-8;-11  
#7:-10;-10  
#8:-11;-9  
#9:-12;-6   
#10:-11;-4  
#11:-10;-3

Now let's modify this code by replacing most of "auto" with "float":

#include <cmath>
unsigned int nump=12u;
float inner=2.5;
float outer=6.0;
float single=2*3.14159265359/nump;
float avg=0.5*inner+0.5*outer;
for (unsigned int i=0u;i<nump;++i){
    float theta=i*single;
    float px=avg*sin(theta);
    float py=avg*cos(theta);
    float tw=17.;
    int v1=std::round(1+px-tw/2.0);
    int v2=std::round(2+py-tw/2.0);
    std::cout<<"#"<<i<<":"<<v1<<","<<v2<<std::endl;
}

and here's the second output:

#0:-8,-2  
#1:-5,-3  
#2:-4,-4  
#3:-3,-7  
#4:-4,-9  
#5:-5,-10  
#6:-8,-11  
#7:-10,-10  
#8:-11,-9  
#9:-12,-7  
#10:-11,-4  
#11:-10,-3

As one can see in line 9 values are different. Any explanation?
PS. OS X 10.12 c++11 and c++14, Apple LLVM 8.1; however was observed also on linux platform with C++17.

UPDATE
As people suggested I modified the code by adding "f" suffix to floating-point values.

unsigned int nump=12u;
auto inner=2.5f;
auto outer=6.0f;
auto single=2.f*3.14159265359f/nump;
auto avg=0.5f*inner+0.5f*outer;
for (auto i=0u;i<nump;++i){
    auto theta=i*single;
    auto px=avg*sin(theta);
    auto py=avg*cos(theta);
    auto tw=17.f;
    int v1=std::round(1.f+px-tw/2.0f);
    int v2=std::round(2.f+py-tw/2.0f);
    std::cout<<"#"<<i<<":"<<v1<<";"<<v2<<std::endl;
}

versus

unsigned int nump=12u;
float inner=2.5f;
float outer=6.0f;
float single=2.f*3.14159265359f/nump;
float avg=0.5f*inner+0.5f*outer;
for (unsigned int i=0u;i<nump;++i){
    float theta=i*single;
    float px=avg*sin(theta);
    float py=avg*cos(theta);
    float tw=17.f;
    int v1=std::round(1.f+px-tw/2.0f);
    int v2=std::round(2.f+py-tw/2.0f);
    std::cout<<"#"<<i<<":"<<v1<<";"<<v2<<std::endl;
}

The result is exactly the same.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
BorisV
  • 683
  • 3
  • 20

2 Answers2

0

2.5 for example is a double type. So inner is a double in your first snippet, but a float in the second. (Note that the expression 2 * 3.14159265359 / nump is a double too.)

So the type conversions are bound to cost precision in places. That is the cause of the difference you observe.

On modern desktop systems you'll likely find that double is faster than a float as in using the latter can cause type conversions (unnoticed by the programmer) at the machine level.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
0

No. auto does not directly affect maths. What does affect maths is the type of your variables involved in the calculation.

float inner=2.5;

This is a float initialized by the floating point literal 2.5 which is of type double.

This on the other hand:

auto inner=2.5;

Declares inner to be initialized with the floating point literal 2.5 which is of type double and the type of inner is deduced from the initializer: innter is a double.

Change your floating point literals to float to get the same results. For example 2.5 -> 2.5f.


auto does not change the meaning of code when you replace it with the exact type that it gets deduced to. If you replace it with a different type then the meaning of the code is changed.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185