Thursday, January 12, 2017

Digest for comp.lang.c++@googlegroups.com - 25 updates in 4 topics

JiiPee <no@notvalid.com>: Jan 12 12:07AM

On 11/01/2017 21:28, Stefan Ram wrote:
> #include <interview.h>
 
 
haha
JiiPee <no@notvalid.com>: Jan 12 12:12AM

On 11/01/2017 22:54, Stefan Ram wrote:
 
> is
 
> if( n == 0 )oops(); else ave = average( a, n )
 
> .
 
I kind of agree with average(). But with opening-a-file error exception
is better. Somehow it feels strainge to use exception with mathematical
calculations. But yes, my interviewer seemed to like it...Well, i forgot
to mention actually any error handling (which was a mistake obviously).
 
 
I kind of agree that in this case its more a documentation issue.
Obviously asserts need to be there for debugging.
David Brown <david.brown@hesbynett.no>: Jan 12 10:36AM +0100

On 11/01/17 20:16, JiiPee wrote:
>> I think the most practically useful behavior would be the 0 return,
>> documented as such.
 
> But average can also be 0, cant it? So we cannot return 0 (zero) ...
 
Of course you can return 0 if you want.
 
The average of any empty set is not defined - it simply does not make
sense to take the sum of the values and divide by the number of values
when the set is empty.
 
So if you are writing a function to calculate an average, you have three
options.
 
First, you can leave it undefined - it's okay to have "garbage in,
garbage out". Just ignore the possibility. This is a perfectly
reasonable attitude, and it is the most efficient one for both developer
time and run time. But it requires that the function be used correctly,
or behaviour is undefined and may launch nasal daemons, corrupt your
files, or anything else.
 
Secondly, you can specify the behaviour of the function with empty sets.
Then it is up to you, as the writer of the specification, to say what
you will do when given an empty set. Possibilities include returning 0,
returning NaN, throwing an exception, calling an error handler, popping
up a message, killing the program with an error message. You can even
return 42 if you like - as long as you say what the function will do in
this case, and do it. Usually it is best to do something obvious and
sensible, of course - returning 0 is fine, but returning 42 would look a
bit odd.
 
Thirdly, you can leave it as unspecified behaviour. Here you say that
the function will return a value of the declared type (double, int,
whatever), without crashing or causing other problems. You just don't
say what number that will be. Typically the implementation will pick a
value (such as 0 or NaN), but you don't specify that value for the function.
 
 
This third option is often the best for general use. If someone uses
the function incorrectly (passing an empty set), they have a bug in
their code - but your function implementation is not going to make the
situation worse. The second option may be nicer as an aid to debugging
- it can make it easier for the person who wrote the code to find
possible errors. The first option is fine when there is tight
cooperation between the author of the function, and its user.
JiiPee <no@notvalid.com>: Jan 12 01:16PM

On 12/01/2017 09:36, David Brown wrote:
>>> documented as such.
>> But average can also be 0, cant it? So we cannot return 0 (zero) ...
> Of course you can return 0 if you want.
 
 
If we have a set of numbers: -1, 0 , 1 we have 3 numbers and their
average value/mean is 0. And there was no errors or dividing by zero... :)
JiiPee <no@notvalid.com>: Jan 12 01:20PM

On 12/01/2017 09:36, David Brown wrote:
> Possibilities include returning 0
 
 
What do you mean by "returning 0"? Lets says the function header is:
 
double average(double values[], int count);
 
So do you mean this functions return value would be 0 if there is an error?
David Brown <david.brown@hesbynett.no>: Jan 12 03:23PM +0100

On 12/01/17 14:16, JiiPee wrote:
>> Of course you can return 0 if you want.
 
> If we have a set of numbers: -1, 0 , 1 we have 3 numbers and their
> average value/mean is 0. And there was no errors or dividing by zero... :)
 
I am perfectly aware that the average of a non-empty set of numbers can
be 0. That does not conflict with 0 being a sensible return value when
the function is called with an empty set. It means that the caller
cannot write:
 
int x = average(set);
if (x == 0) {
printf("The set was empty\n");
} else {
printf("The average is %i\n, x);
}
 
But unless the user of the function particularly incompetent, or you
have specifically said the function will handle empty sets in a way that
is suitable here, then the user will never do this. Instead, they will
write:
 
if (isempty(set)) {
printf("The set was empty\n");
} else {
int x = average(set);
printf("The average is %i\n, x);
}
 
The reason you make the function return 0 on an empty set is so that
when a user writes this :
 
int x = average(set);
printf("The average is %i\n, x);
 
and "set" happens to be empty, then they will get the output "The
average is 0\n", rather than "Launching nasal daemons...\n".
David Brown <david.brown@hesbynett.no>: Jan 12 03:28PM +0100

On 12/01/17 14:20, JiiPee wrote:
 
> What do you mean by "returning 0"? Lets says the function header is:
 
> double average(double values[], int count);
 
> So do you mean this functions return value would be 0 if there is an error?
 
double average(double values[], int count) {
if (count <= 0) return 0;
return std::accumulate(values, values + count, 0.0) / count;
}
 
It won't return 0 on all errors - such as mismatches between the actual
array size and count. But it will return 0 on an empty set.
JiiPee <no@notvalid.com>: Jan 12 03:40PM

On 12/01/2017 14:28, David Brown wrote:
> if (count <= 0) return 0;
> return std::accumulate(values, values + count, 0.0) / count;
> }
 
 
But this would give a wrong answer if you call this function with:
 
values[] = {-1,0,1}
 
isnt it? Because it would return 0 and so the receiver would think there
was some kind of error, right?
 
But +1 for the std::accumulate! :)
David Brown <david.brown@hesbynett.no>: Jan 12 04:52PM +0100

On 12/01/17 16:40, JiiPee wrote:
>> }
 
> But this would give a wrong answer if you call this function with:
 
> values[] = {-1,0,1}
 
No, it gives the correct answer - 0.
 
 
> isnt it? Because it would return 0 and so the receiver would think there
> was some kind of error, right?
 
No, the receiver would got 0 would only think there is an error if he
did not understand how to use the function properly. And if that is the
case, then returning 0 is just minimising the spread of damage due to
the user's mistake.
 
The user cannot use a result of 0 to conclude that there was an error
any more than he can use a result of 1 to conclude that the set passed
was { 0, 1, 2 }.
 
 
JiiPee <no@notvalid.com>: Jan 12 04:13PM

On 12/01/2017 14:23, David Brown wrote:
> printf("The average is %i\n, x);
 
> and "set" happens to be empty, then they will get the output "The
> average is 0\n", rather than "Launching nasal daemons...\n".
 
 
I see, so you just want to prevent a crash if all debugging and testing
fails to find that error.
 
Because an assert() would do the job, but I guess you think debugging
cannot find the errror situation?
JiiPee <no@notvalid.com>: Jan 12 04:27PM

On 12/01/2017 14:23, David Brown wrote:
> printf("The average is %i\n, x);
 
> and "set" happens to be empty, then they will get the output "The
> average is 0\n", rather than "Launching nasal daemons...\n".
 
 
I see. But in this case I would prefer to use NaN or max_double so the
user would see there is something wrong going on. Because 0 return looks
like a success, but getting max_double would surely be noticed.
David Brown <david.brown@hesbynett.no>: Jan 12 05:35PM +0100

On 12/01/17 17:13, JiiPee wrote:
> fails to find that error.
 
> Because an assert() would do the job, but I guess you think debugging
> cannot find the errror situation?
 
It won't necessarily prevent a crash. It will simply provide a
consistent, efficient, and not unreasonable value in the case of an
unreasonable call. In some cases, it might even be considered a useful
part of the specification of the function that the user could rely on
(so that the user does not need to check for empty sets before calling
average).
David Brown <david.brown@hesbynett.no>: Jan 12 05:37PM +0100

On 12/01/17 17:27, JiiPee wrote:
>> average is 0\n", rather than "Launching nasal daemons...\n".
 
> I see. But in this case I would prefer to use NaN or max_double so the
> user would see there is something wrong going on.
 
Feel free - it is your choice.
 
Personally, I don't like NaNs, and I don't have any use for max_double
because I don't like comparing floating point types for equality (even
though it would work in this case). And I don't like the idea that a
function might fail and return a weird value - to mind mind, functions
never fail, only specifications.
 
JiiPee <no@notvalid.com>: Jan 12 04:44PM

On 12/01/2017 16:37, David Brown wrote:
> And I don't like the idea that a
> function might fail and return a weird value - to mind mind, functions
> never fail, only specifications.
 
 
But the way you use that function, the following situation could happen:
 
The user read values from a file and gets a zero set and calculates the
average using. The coder forgot to check the zero set (a bug in the
code) so the program prints:
 
> Average is 0.
 
But if you return max_double it would print like:
 
> Avarage is 99999999999999.
 
which one makes it easier to find that there was a hidden error? :)
 
The second one, right? So the user of the program can now report this
error and fix. But if the use gets 0, then they think all is fine and
they might try to find the error from other place later on.
JiiPee <no@notvalid.com>: Jan 12 04:46PM

On 12/01/2017 16:44, JiiPee wrote:
 
> The second one, right? So the user of the program can now report this
> error and fix. But if the use gets 0, then they think all is fine and
> they might try to find the error from other place later on.
 
So I a little bit agree with C-programmers argument here that "its good
that the program crashes... at least we can find the error then", rather
than a hidden error and then difficult to find where it is. At least
here we know where the error is.
JiiPee <no@notvalid.com>: Jan 12 04:48PM

On 12/01/2017 16:37, David Brown wrote:
> Personally, I don't like NaNs, and I don't have any use for max_double
> because I don't like comparing floating point types for equality (even
 
We do not need to test for equality... its just that the number is very
strange, so the user will spot the error and thus we can fix the error.
 
> though it would work in this case). And I don't like the idea that a
> function might fail and return a weird value
 
But I prefer to get a very weird value that getting a which looks good
but its not. Its like a wolf in sheeps clothing....
Real Troll <real.troll@trolls.com>: Jan 12 12:55PM -0400

On 11/01/2017 18:17, JiiPee wrote:
> zero but other ways. What would be the best way for the function to
> report about "dividing by zero" case? How would you do it?
 
> I kind of agree with Bjarne here.... do you?
 
Try this:
 
<http://stackoverflow.com/questions/6121623/catching-exception-divide-by-zero>
 
Good luck.
JiiPee <no@notvalid.com>: Jan 12 04:51PM

On 12/01/2017 16:48, JiiPee wrote:
>> function might fail and return a weird value
 
> But I prefer to get a very weird value that getting a which looks good
> but its not. Its like a wolf in sheeps clothing....
 
 
Somebody reporting the result, if they see: "Average is 0." in a case
there was a zero set, then they have no clue its wrong and they would go
on and report a wrong result. But if that person sees a result: "Average
is 999 exp+395" they surely will not go on and report that, but they
start thinking: "oh, something is wrong here... i ll contact the coder..."
JiiPee <no@notvalid.com>: Jan 12 04:53PM

On 12/01/2017 16:55, Real Troll wrote:
> Try this:
 
> <http://stackoverflow.com/questions/6121623/catching-exception-divide-by-zero>
 
> Good luck.
 
 
the third answer there says:
 
"Stroustrup says, in "The Design and Evolution of C++" (Addison Wesley,
1994), "low-level events, such as arithmetic overflows and divide by
zero, are assumed to be handled by a dedicated lower-level mechanism
rather than by exceptions. This enables C++ to match the behaviour of
other languages when it comes to arithmetic. It also avoids the problems
that occur on heavily pipelined architectures where events such as
divide by zero are asynchronous."`"
David Brown <david.brown@hesbynett.no>: Jan 11 09:12AM +0100

On 11/01/17 01:46, Richard wrote:
> implementation, it doesn't surprise me that it was considered too
> green for C++17. They are really cautious about introducing new stuff
> into the standard that hasn't been well tested.
 
Some things get in faster, but I suppose in this case if the module
system under test turns out to have subtle flaws, it could cause /real/
problems for the future.
 
 
> I consider the standards proposal to be an evolution of the clang
> system instead of a competing system. It is different because it
> incorporates the lessons learned from the clang experiments.
 
Fair enough.
 
 
> Lots of proposed stuff for C++11, C++14 and C++17 has been implemented
> from working paper proposals and the working proposal from Gabriel Dos
> Reis et al seems good enough to me to start a working implementation.
 
Maybe they just haven't got round to it yet - there is no shortage of
tasks for the gcc developers (or clang developers, or, I expect, MSVC
developers). But if MSVC implements this, and clang update their
implementation to the same working paper proposal, then I would expect
gcc to follow if the current proposal is considered solid enough. It's
good not to have too many highly experimental implementations of a
feature, but also good to have more implementations once the feature
nears stability.
jonkalb <google@kalbweb.com>: Jan 11 07:55PM -0800

On Wednesday, January 11, 2017 at 10:06:59 AM UTC-8, Scott Lurndal wrote:
 
> C++ was perfect at version 2.1, and has been going downhill
> ever since.
 
I've heard of C++98, C++03, C++11, C++14, and C++17, but I've never heard of C++ version 2.1.
Robert Wessel <robertwessel2@yahoo.com>: Jan 11 10:21PM -0600

On Wed, 11 Jan 2017 19:55:32 -0800 (PST), jonkalb <google@kalbweb.com>
wrote:
 
 
>> C++ was perfect at version 2.1, and has been going downhill
>> ever since.
 
>I've heard of C++98, C++03, C++11, C++14, and C++17, but I've never heard of C++ version 2.1.
 
 
Before standardization, C++ usually had version numbers. C++2.0 was
mostly what was described by the second edition of Stroustrup's "The
C++ Programming Language", or roughly the language as of 1989 (the
book was published in 1991). What's called 2.1 is, I think, what
corresponds to the 3rd edition of that book (published 1997),
reflecting the language of a year or two prior to that.
 
All approximately.
scott@slp53.sl.home (Scott Lurndal): Jan 12 01:30PM

>book was published in 1991). What's called 2.1 is, I think, what
>corresponds to the 3rd edition of that book (published 1997),
>reflecting the language of a year or two prior to that.
 
2.1 came out about 1991, IIRC. We started using C++ in
1989 for an operating system project, and upgraded to
Cfront 2.1 about '91 or thereabouts.
 
I think the 3rd edition of the book represents C++ 3.0
which was the first release to have templates and exceptions.
 
(In those days, C++ was compiled to C then compiled with
a vanilla C compiler (we used a port of PCC for the motorola
88100 RISC processor))
Andrey Karpov <karpov2007@gmail.com>: Jan 12 03:54AM -0800

PVS-Studio is a static code analyzer, that searches for errors and vulnerabilities in programs written in C, C++ and C#. In this article, I am going to uncover the technologies that we use in PVS-Studio analyzer. In addition to the general theoretical information, I will show practical examples of how certain technology allows the detection of bugs. Article: http://www.viva64.com/en/b/0466/
"Chris M. Thomasson" <invalid@invalid.invalid>: Jan 11 02:50PM -0800

On 1/9/2017 11:02 PM, Alf P. Steinbach wrote:
 
> It's hard top come up with a good name for `exec` here, but I've landed
> on `result_for`, because that makes the calling code readable:
 
> `func_foo::result_for(i )`.
 
Agreed.
 
 
> C++11 added support that means the input structure can be specified
> inline, as in the call `func_foo::exec({1, 2, 3})`.
 
Indeed. FWIW, sometimes I like to create the "input" structure ahead of
time, especially if it has many "parameters". Another contrived reason
is the ability to reuse a similar "template like" input structure cast
over many calls to (::result_for(i)) in the same scope.
 
 
 
> cout << quotient << ',' << remainder << endl;
> }
> [/code]
 
This looks very nice, however, imvvho this seems like a bit of a
"different" language to me. I understand auto, but personally still like
a type name in the source code:
___________________________
auto i0 = 123.0;
auto i1 = 123.0f;
 
vs:
 
double i0 = 123.0;
float i1 = 123.0f;
___________________________
 
Ahh, perhaps I need to brush up on my modern C++ skills!
 
;^o
 
 
FWIW, here is a little example of where I might want to use the input
output binding type thing. Here is a function that can find cycles in
the Mandelbrot set. It uses a slow and fast iteration "pointer",
basically identical to finding cycles in linked lists.
 
Here is the crude code using the "free-function" input/output
encapsulation "thing":
_____________________________________________
#include <complex>
#include <cstdio>
 
 
typedef double ct_float;
typedef std::complex<ct_float> ct_complex;
 
 
bool
ct_complex_compare(
ct_complex const& c0,
ct_complex c1,
ct_float epsilon
) {
ct_complex d = c1 - c0;
return std::abs(d) < epsilon;
}
 
 
struct mbrot_detect_cycle
{
struct input
{
ct_complex c;
ct_complex z;
ct_float escape;
ct_float epsilon;
unsigned int imax;
};
 
struct output
{
ct_complex z;
unsigned int i;
bool cycle;
};
 
static output result_for(input const& in)
{
ct_complex slow = in.z;
ct_complex fast = in.z;
 
for (unsigned int i = 0; i < in.imax; ++i)
{
slow = slow*slow + in.c;
 
fast = fast*fast + in.c;
fast = fast*fast + in.c;
 
if (ct_complex_compare(slow, fast, in.epsilon))
{
return{ slow, i, true };
}
 
ct_float dis = std::abs(slow);
 
if (dis > in.escape)
{
return{ slow, i, false };
}
 
// uncomment following line for progress meter... ;^)
//if (! (i % 10000)) std::printf("i:%u\r", i);
}
 
return{ slow, in.imax, false };
}
};
 
 
 
int main()
{
{
mbrot_detect_cycle::input in = {
// fine grain epsilon takes many iterations
// for this point (-.75, 0):
{ -.75, 0 },
{ 0, 0 },
2,
.0001,
500000000
};
 
mbrot_detect_cycle::output out =
mbrot_detect_cycle::result_for(in);
 
if (out.cycle)
{
std::printf(
"cycle found for in.c:(%f, %f) "
"at out.i:(%u) iterations in.epsilon:(%f)\n",
in.c.real(), in.c.imag(), out.i, in.epsilon);
}
 
else
{
std::printf(
"** NO ** cycle was found for in.c:(%f, %f) "
"at out.i:(%u) iterations in.epsilon:(%f)\n",
in.c.real(), in.c.imag(), out.i, in.epsilon);
}
}
 
return 0;
}
_____________________________________________
 
 
FWIW, one can try using different points to test. FWIW, I get the
following output for this code:
_____________________________________________
cycle found for in.c:(-0.750000, 0.000000) at out.i:(4291771) iterations
in.epsilon:(0.000100)
_____________________________________________
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: