Function to always round up to the nearest tenth

Pages: 12345
Well, it's just boring again... Guess I'll go with traditional while-do loop instead :)
I agree with cire :+)
closed account (48T7M4Gy)
Agree with what may I ask?
kemort wrote:
@cire says:
But, hey... keep talking out of your (ass) and filling the forums with misinformation and novice code while pretending you are an expert. I'm sure you are impressing yourself.


This sort of disgraceful language, exaggeration and bullying will not be tolerated Cire. Stop it and apologise.
Last edited on
closed account (48T7M4Gy)
I'll take you silence as agreement with cires cowardly attack TIM . That puts you in serious breach of the APS code of conduct and you can expect this won't be the last you hear of it.
> If a program shall not call main, but can be compiled with warnings, and executed,
> and given the above paragraph does this mean it is UB?

No. Using the function main (the main at global unnamed scope) from within a program is simply an "erroneous program construct" that must be diagnosed by a conforming implementation.

int + double * noexcept = const[for+while-if] ; is another "erroneous program construct" that must be diagnosed by a conforming implementation. Undefined behaviour does not come into the discussion.

Many erroneous program constructs do not engender undefined behaviour; they are required to be diagnosed. - IS
I see cire's comment as banter, nothing more. Like, let it through to the keeper :+)

Are people that thin skinned that they can't take a little ribbing? Here are some examples from where I used to work:

DALE! DALE, sit up straighter. What???? If you are hunched over your desk like that, your nose is too close to your ass !!

Gazza, we are going to give you some serious banter, so don't get upset OK? Right-oh :+| You know that brand new Mitsubushi Pajero you bought the other day? Yeah? :+| You know that Pajero means wanker in Spanish? :+D

All this came from a large South African bloke (aka Baboon, but he promoted himself to Gorilla). He was a devout Christian, I didn't believe it at first, but it was true.

What is APS code of conduct?
@JLBorges

Ok thanks :+)
closed account (48T7M4Gy)
Tolerate bullies as much as you want. I don't. You don't need to protect them TIM, that's part of their sociopathic behavior pattern getting your agreement to take sides. Passive hostility and calling me a wanker doesn't work either.

Passive hostility and calling me a wanker doesn't work either.


Come on, that was quite clearly was not directed at you - it was an actual conversation between workmates some years ago. I only get away with posting it because it is specifically not directed at anyone, and should be seen as a form of comedy. The point was, it is a just little ribbing - a storm in a teacup. You know, laugh at it, duck under it, let it slide - whatever.


Edit: Btw spamming the forum with nasty messages about cire, probably won't get you anywhere - it will just add to your report count.
Last edited on
closed account (48T7M4Gy)
TIM I suggest you buy out of this. You have no right to take sides and protect a sociopath - and I use the description advisedly. Cire is a destroyer and is amongst a small group who are hellbent on bullying and spoiling this forum.

It goes beyond ribbing and is better described as abuse.

I'm sorry that you don't have sufficient life experience on how much the world has changed in tackling sociopaths but it's sufficient to say you don't need to protect the coward Cire and a couple of other pests here.

It's not a storm in a teacup. You wouldn't have put your toe in the ring if you thought it was. Your tactics don't work. Exposing the sociopaths does!
TIM I suggest you buy out of this.


Ok, but definitely not for any of the reasons you mentioned. It's 02:30AM at this end, I might just go to bed and lower my own testosterone levels :+D Might even change my username to Pajero :+D
closed account (48T7M4Gy)
Btw spamming the forum with nasty messages about cire, probably won't get you anywhere - it will just add to your report count.


It's not spamming and, quoting a coward, bully and calling out a sociopath isn't nasty - being a frightened apologist for one is!

As for the report count - boy oh boy, surely you can't be serious.
Woah. This thing has gone off the rails while I was sleeping.

TheIdeasMan wrote:
With a normal recursive function the compiler puts the info it needs into a stack frame for each function call, and pushes this stack frame onto the stack. With each call to main - it's the same, but this time there is all the information associated with main (all it's local variables amongst other things), so it leads to a SO earlier.
I don't see why you think these two clauses are not identical:

the info it needs into a stack frame
this time there is all the information associated with main (all it's local variables amongst other things)

Creating a stack frame for a function involves setting stack space aside for all the local data used by the function.
Hello again,

To the dead person : If you wish to continue to participate in this topic, feel free to reincarnate.

Yeah, I have reincarnated.

Not very sure what I did to even deserved this...

Also, it seems that you guys were at war when I was away.

So from things that others have pointed out, I admit that there is something in my solution. It still produces correct results to some extent, it is just it is not perfect. I took my time to modify the close account's solution the way that I see fit. Here is my code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
#include <cstdlib>

using namespace std;

bool need_random = true;

double random_d(int &precision)
{
    if(need_random) {
        srand(time(NULL)); 
        need_random = false;
    }

    int n = (rand() % 9) + 1;
    if((rand() % 100) >= 85) n = 1;
    double a = (rand() % 15000);
    double b = 0;
    for(int i = 0, j = 0; i < n; i++)
    {
        j = (rand() % 9) + 1;
        b = b * 10 + j;
    }

    precision = ceil(log10(b));

    a += (b / pow(10, precision));

    return a;
}

double round_d(double d, int precision)
{
    stringstream ss;
    ss.setf(ios::fixed);
    ss.precision(precision);
    ss << d;

    bool round = false;
    string out = ss.str();
    int n, dot = out.find(".");

    if(dot != string::npos && ((out.length() - 1 - dot) >= 2) && (round = true))
    n = dot + 1 + 1; 
    else n = out.length();

    out.resize(n);
    ss.str(""); ss.clear(); 

    ss.str(out);
    ss >> d;
    if(round) d += 0.1;

    return d;
}

int main()
{
    int precision;
    double d;

    for(int N = 25; N > 0; N--)
    {
       cout.setf(ios::fixed);
       cout << "in : ";
         
        cin >> d;
        cout << "precision : ";
        cin >> precision; 

        // d = random_d(precision);
        // cout.precision(precision);
        // cout << d << endl;
 
        d = round_d(d, precision);

        cout.precision(1);
        cout << "out : " << d << endl << endl;
    }
}


My problem is : I must have to supply correct decimal precision whenever I manually input a decimal number. I don't want to input a number and then its precision in order to make the algorithm run correctly. For example :

in : 25.086
precision : 3

in : 985
precision : 0

in : 94.2602672
precision : 7

Could anyone help me get rid of this additional step please?
helios wrote:
I don't see why you think these two clauses are not identical:


They are, but the second one emphasises that main could have a much larger stack frame. Hence possibly a SO earlier.

Anyway, all this is purely academic - probably not worth pursuing it any further.
This would work accurately for values with a reasonably small number of digits.

1
2
3
4
5
6
7
unsigned long long ipow10( unsigned int p ) { return p == 0 ? 1 : 10 * ipow10(p-1) ; }

double do_round( double d, unsigned int prec )
{
    const auto pow = ipow10(prec) ;
    return std::round( d * pow ) / pow ;
}

http://coliru.stacked-crooked.com/a/4df62254186e8b60
http://rextester.com/ITJYH92464
QuestionMaker3 wrote:
Not very sure what I did to even deserved this...


You didn't do anything wrong :+) It's just that we seem to have a member who likes to report everyone. Because you had a low post count, once reported enough the account is automatically closed.

So back to the task at hand.

In closed account 5a8Ym39o6 code, the precision was not something that had to be specified by the user. It was sent to the round_d function un-initialised, but then set inside the function. It is only there to provide some randomness for the input, for demonstration purposes. But you have real input, so you might not need that function at all.

When I compile that code I get these warnings, most of them came from closed account's code:
List of warning options here:
http://www.cplusplus.com/forum/general/183731/#msg899203

../Rounding/main.cpp:28:17: warning: implicit conversion turns floating-point number into integer: 'double' to 'int' [-Wfloat-conversion]
    precision = ceil(log10(b));
              ~ ^~~~~~~~~~~~~~
../Rounding/main.cpp:14:15: warning: implicit conversion loses integer precision: 'time_t' (aka 'long') to 'unsigned int' [-Wshorten-64-to-32]
        srand(time(NULL));
        ~~~~~ ^~~~~~~~~~
../Rounding/main.cpp:46:52: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
    if(dot != string::npos && ((out.length() - 1 - dot) >= 2) && (round = true))
                                                 ~ ^~~
../Rounding/main.cpp:50:16: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long') [-Wsign-conversion]
    out.resize(n);
    ~~~        ^
../Rounding/main.cpp:44:18: warning: implicit conversion loses integer precision: 'size_type' (aka 'unsigned long') to 'int' [-Wshorten-64-to-32]
    int n, dot = out.find(".");
           ~~~   ^~~~~~~~~~~~~
../Rounding/main.cpp:46:12: warning: comparison of integers of different signs: 'int' and 'const size_type' (aka 'const unsigned long') [-Wsign-compare]
    if(dot != string::npos && ((out.length() - 1 - dot) >= 2) && (round = true))
       ~~~ ^  ~~~~~~~~~~~~
../Rounding/main.cpp:48:14: warning: implicit conversion loses integer precision: 'size_type' (aka 'unsigned long') to 'int' [-Wshorten-64-to-32]
    else n = out.length();
           ~ ^~~~~~~~~~~~
7 warnings generated.


So I fixed up all the warnings, removed the side effect code, changed the types, renamed a variable, removed namespace std, moved the functions to after main.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
#include <cstdlib>

double random_d(std::streamsize& input_precision);
double round_d(double d,  std::streamsize input_precision);

int main()
{
    std::streamsize input_precision = 0; // I like to avoid naming variables the same as something in the STL, despite knowing what std:: does
    double d = 0.0;
    const int test_cases = 25;

    for(int N = 0; N < test_cases; ++N)
    {
       std::cout.setf(std::ios::fixed);
       std::cout << "in : ";

//        std::cin >> d;
//        std::cout << "precision : ";
//        std::cin >> input_precision;

         d = random_d(input_precision);
         std::cout.precision(input_precision);
         std::cout << d << "\n";

        d = round_d(d, input_precision);

        std::cout.precision(1);
        std::cout << "out : " << d << "\n\n";
    }
}

// generates some random numbers with a random amount of precision
double random_d(std::streamsize& input_precision)
{
    static bool need_random = true;

    if(need_random) {
        srand(static_cast<unsigned int>( time(NULL)) );
        need_random = false;
    }

    int n = (rand() % 9) + 1;
    if((rand() % 100) >= 85) n = 1;
    double a = (rand() % 15000);
    double b = 0;
    for(int i = 0, j = 0; i < n; i++)
    {
        j = (rand() % 9) + 1;
        b = b * 10 + j;
    }

    input_precision = static_cast<std::streamsize>( std::ceil( log10(b)) ) ;

    a += (b / std::pow(10, input_precision));

    return a;
}

// does the rounding 
double round_d(double d,  std::streamsize input_precision)
{
    std::stringstream ss;
    ss.setf(std::ios::fixed);
    ss.precision(input_precision) ;
    ss << d;

    bool round = false;
    std::string out = ss.str();
    std::string::size_type n;
    std::size_t dot = out.find(".");

    if(dot != std::string::npos && (out.length() - 1 - dot) >= 2) {
        round = true;
        n = dot + 2;
    }
    else {
        n = out.length();
    }

    out.resize(n);
    ss.str(""); ss.clear();

    ss.str(out);
    ss >> d;
    if(round) d += 0.1;

    return d;
}


As I said you could alter this to not use the random_d function or any precision. Although you could have a variable which controls how many decimal places the output should have - possibly 2 or 3 or whatever number of dp.

Hope this helps :+)

They are, but the second one emphasises that main could have a much larger stack frame.
The size of a function's stack frame is exactly dependent on the total sum of local data it allocates. main() could have the biggest stack frame of the program, or the smallest one.
Which of these do you think will overflow after fewer recursive steps?
1
2
3
4
5
6
7
8
void f(){
    int x[1000];
    f();
}

int main(){
    return main();
}
Along the same lines as posted earlier, using the C++ library for random numbers:
1
2
3
4
5
6
7
8
9
10
11
12
13
unsigned long long ipow10( unsigned int p ) { return p == 0 ? 1 : 10 * ipow10(p-1) ; }

double do_round( double d, unsigned int prec )
{
    const auto pow = ipow10(prec) ;
    return std::round( d * pow ) / pow ;
}

double random_double( unsigned int prec, int min_v = 0, int max_v = 10.0 )
{
    static std::mt19937 rng { std::random_device{}() } ;
    return do_round( std::uniform_real_distribution<double>( min_v, max_v )(rng), prec ) ;
}

http://coliru.stacked-crooked.com/a/e847a2de30c1b883
Pages: 12345