C++Guns – RoboBlog blogging the bot

21.09.2015

Depends: but it is not going to be installed - resolve apt dependencies

Filed under: Allgemein — Tags: — Thomas @ 17:09

Edit file
/var/lib/dpkg/status

Search for packet with dependency problem. Edit dependency list and fix version numbering to a version, that is installed.

ganglia lm-sensors

Filed under: Allgemein — Tags: — Thomas @ 14:09

thomas@H8QGL:~$ cat gmetric-cpu-temp 
#!/bin/bash
# this script read the core(s) temperature using lm sensors then calculate the average
# and send it to the ganglia using gmetric
# assumes that the lines reported by lm sensors are formated like this
# Core 0: +46.0 C (high = +80.0 C, crit = +100.0 C)

SENSORS=/usr/bin/sensors
GMETRIC=/usr/bin/gmetric

#sensors
let count=0
sum=0.0
for temp in $($SENSORS | grep temp  |  grep -e '+.*C' | cut -f 2 -d '+'  | sed 's/°/ /g' | cut -f 1 -d ' '); do
    if (($(echo "$temp > 1.0" | bc) ))
    then
      sum=$(echo $sum+$temp | bc);
#    echo $temp, $sum, $count
      let count+=1;
    fi
done
temp=$(echo "scale=1; $sum/$count" | bc)
#echo $temp
$GMETRIC -t float -n "avg temp" -u "Celcius" -v $temp

Fehlerhaftes Original here: http://computational.engineering.or.id/LM_Sensors#Integrasi_Dengan_Ganglia
In meiner Version wird das Grad-Celsius Zeichen rausgefiltert.
Es werden nur echte Temperaturen verrechnet, keine min und max Werte.
Falsche Temperaturen wie z.b. 0.8C werden ignoriert nud erst ab 1Grad verrechnet.


thomas@H8QGL:~$ cat /etc/cron.d/sensors 
* * * * * root /usr/local/bin/gmetric-cpu-temp 

29.07.2015

DerivedFunctor - fancy

Filed under: Allgemein — Tags: — Thomas @ 22:07

In C++11 kann man von einer Funktion erben. Krass.
Lambdas sind krass.
Das typedef musste sein, sonst hat er nicht compiliert. Ist vllt aber
nur ein Compilerbug und bald nicht mehr nötig.

auto foo = [](){return 42;};

class DerivedFunctor : public decltype(foo)
{
  typedef decltype(foo) type;
  public:
    DerivedFunctor(type foo)
    : type(foo)
    {
    }

    auto operator()() {
      cout << "DerivedFunctor::operator()\n";
      return type::operator()();
    }
};

int main() {
  DerivedFunctor t(foo);
  cout << t();
}

26.07.2015

Replace runtime constant wich template variables

Filed under: Allgemein — Tags: — Thomas @ 09:07

void version1(int i, int h) {
  // if(h) is evaluated every call
  if(h==0) {
  }
  else if(h==1) {
  }
  else {
  }
}

template
void version2(int i) {
  // if(h) is evaluated at compile time
  if(h==0) {
  }
  else if(h==1) {
  }
  else {
  }
}

void func(int h) {
  // h is a runtime constant for this function
  for(int i=0; i < 1e7; ++i) {
    version1(i, h);
  }

  // here,h is evaluated at runtime but outside the loop.
  // the compiler create three different version of version2 each for every h
  if(h==0) {
    for(int i=0; i < 1e7; ++i) {
      version2<0>(i);
    }
  }
  else if(h==1) {
    for(int i=0; i < 1e7; ++i) {
      version2<1>(i);
    }
  }
  else {
    for(int i=0; i < 1e7; ++i) {
      version2<2>(i);
    }
  }
}

int main() {
  int h=0;
  func(h);

  h=1;
  func(h);
}

25.06.2015

Warum wird bei der Varianz durch n-1 geteilt?

Filed under: Allgemein — Tags: — Thomas @ 19:06

Warum wird bei der Varianz durch n-1 geteilt?
Google bietet bestimmt eine fülle an Antworten. Hier ist noch eine:

1/(n-1) * SUM_i=1,n(xi-xavg)^2
Man teilt durch die Anzahl der Freiheitsgerade. Lässt man das Quadrat in der Summe weg, so ergibt die Summe 0. Der n-te Term ist gleich minus der Summe der vorherigen Terme. Dadurch ist der n-te Term eindeutig festgelegt. Der Freiheitsgrad beträgt nur noch n-1

Update 12.2018
Das nennt sich wohl Bessel's correction

In statistics, Bessel's correction is the use of n ? 1 instead of n in the formula for the sample variance and sample standard deviation, where n is the number of observations in a sample. This method corrects the bias in the estimation of the population variance. It also partially corrects the bias in the estimation of the population standard deviation. However, the correction often increases the mean squared error in these estimations. This technique is named after Friedrich Bessel.

10.06.2015

explicit constructor (Bug of the day 9)

Filed under: Allgemein — Tags: — Thomas @ 18:06

Hmm nicht einfach diesen Fehler zu erklären. Man braucht eine Basis Klasse, zwei abgeleitete Klassen und eine template Funktionen bei der man den Template Teil vergessen hat.

Die Idee ist folgende:
Irgendeine Funktion die irgendeinen Algorithmus ausführt, bekommt ihre Daten über einen Container per Funktionsparameter. Der Container kann alles mögliche sein: vector, list, stack array oder eigene Klassen die einen standard Container erweitern.
Für den Funktionsparameter, also den Container, benutzt man templates, damit der Algorithmus auf allen möglichen Datenstrukturen funktioniert und nur einmal implementiert werden muss.
Das ist gängige Praxis und funktioniert gut.

Nun habe ich zwei neue Klassen erstellt, die von z.B. std::vector erben. Im weiteren ist das die Basis Klasse. Diese Klassen speichern noch eine weitere Information. Welche, ist egal für dieses Beispiel. Nennen wir diese neuen Container Klassen Derived und Derived2.

Die Funktion sieht also so aus:

void func(const Derived &container);

Ich benutzt keine Templates, weil ich sie wie gesagt vergessen hatte. Das war Fehler Nr. 1. Der Code compilierte dennoch ;)

Da die neuen Container Klassen Derived und Derived2 beide von der Klasse Base erben, dachte ich, ein Constructor der eine Instanz der Base Klasse entgegen nimmt ist nicht soo verkehrt. Es ist dann bequem möglich seine Container mit den Standard Container von c++ zu initialisieren. Das war der zweite Fehler. Es ist im Grunde nicht falsch, nur man braucht es nicht, da wir ja templates nutzen. (Aber nicht implementieren).

Beim dritten Fehler habe ich die Coding Style Regeln nicht beachtet. Die besagt, dass man einen Constructor mit nur einem Argument als explicit deklarieren sollte. Siehe z.B. den Kram von google [1]

Normally, if a constructor can be called with one argument, it can be used as a conversion. Declaring a constructor explicit prevents it from being invoked implicitly as a conversion

Und genau das ist passiert. Ich habe func() mit einem Derived2 Object aufgerufen, und es wurde mangels templates in ein Derived Object umgewandelt. Dabei gingen natürlich die zusätzlichen Informationen verloren, welche diese Klassen speichern sollten.
Eine direkte Umwandlung der beiden Derived Klassen hatte ich nicht implementiert, da sie nicht sinnvoll sind.
Die Umwandlung erfolge über die Basis Klasse. Ein Derived2 Object ist ein Base Object. Und Derived kann mit Base Objecten initialisiert werden.

Das ist alles valid und der Compiler sieht kein Fehler. Aber es sollte zumindest ein Warning für den nicht expliciten Constructor geben. Zumindest bei GNU und clang habe ich nichts dergleichen gefunden. Der Intel Compiler kann es aber wohl [2] (Diagnostic 2304: non-explicit constructor with single argument may cause implicit type conversion).

Was lernen wir daraus? Coding Styles, und sich auch daran halten, retten Leben ;) Und nicht so bescheuert Programmieren ;)

Hätte man den Fehler durch ausgiebiges Testen der Funktion hätte finden können? Ja ich denke schon. Aber der Test muss gut sein. In meinem Fall hatte ich nur ein paar einfache Daten getestet und nichts bemerkt. Erst als ich einen anderen Fehler mit dem Debugger suchte ist es mir aufgefallen.

Im Anhang noch der Beispiel Code.explicitctor.cpp.zip

[1] https://google-styleguide.googlecode.com/svn/trunk/cppguide.html
[2] https://software.intel.com/en-us/forums/topic/335573

02.06.2015

QString to std::string (Bug of the day 8)

Filed under: Allgemein — Tags: , — Thomas @ 11:06
std::string class::func() const noexcept {
    return name.toLatin1().constData();
}

3 convertions. From QString to QByteArray to const char* to std::string. Lets see if it works. From Qt Docu

const char * QByteArray::?constData() const
Returns a pointer to the data stored in the byte array. The pointer can be used to access the bytes that compose the array. The data is '\0'-terminated unless the QByteArray object was created from raw data.

basic_string( const CharT* s, const Allocator& alloc = Allocator() )
Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. The behavior is undefined if s does not point at an array of at least Traits::length(s)+1 elements of CharT.

Okay this should work, but can fail.

Using Qt function to convert QString to std::string is the better solution:

std::string QString::toStdString() const

29.05.2015

warning: conversion to 'float' from 'int' may alter its value [-Wconversion] (Bug of the day 7)

Filed under: Allgemein — Tags: , , — Thomas @ 22:05

Another bug of the day :D

You can do the following

float var = float(vari); // yes I know I'm loosing precision
int var = int(std::floor(varf)) // yes I know interger can overflow
int var = qFloor(varf) // Qt version

Same for double.

warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

Tricky one. Usually don't use unsigned types. The world is full of negative value. Use signed types.
Except for..
Array index. To access the full 32/64bit address space, one must use unsigned type.

Let variable data be a pointer/array.
data[i] is the same as data+i
Now variable i should have the same wide as data. Which is size_t. Type size_t is 32bit wide on 32bit system and 64bit otherwise.
New rule: Always use size_t for index variable while accessing data. Don't use int.

Type size_t is an unsiged type.
New rule: Never count backwards in for loops while accessing data.

Consider this endless loop
for(size_t i=data.size(); i >= 0; i--)

If i == 0 and i-- then i == 2^32-1 which is > 0. Damn.
There are a lot of solutions. Bad one and really bad ones. Here is my perfect one: You count forward. That is really easy and everybody understands what is going one and there are no surprises.
In the next line you subtract n-i-1 and volia. Perfect.

for(size_t ri=0; ri < data.size(); ri++) { size_t i = data.size() - ri - 1; I named the new loop variabl ri for reverse iterator. Don't forget to add -1. Arrays start by 0. You can of couse use std::reverse_iterator But hey, I love for loops!

2.1GB limit Qt Container (Bug of the day 6)

Filed under: Allgemein — Tags: , — Thomas @ 13:05

Diesmal hab ich mir selbst in den Fuß geschossen. Zum zweiten mal in den selben.

Alle Qt Container können nur maximal 2.1GB allocieren. Das ist eine Design Entscheidung von Qt. Dummerweise wird keine Fehlermeldung erstellt falls man mehr Speicher braucht. Ich kann schon verstehen, dass es irgendwie falsch ist, wenn eine GUI Anwendung auf einmal Tonnen von GB brauch. Aber einfach ein Absturz zulassen ist schlampig.

Warum 2.1GB? Das entspricht der Anzahl der Bytes die ein signed 32bit integer darstellen kann. Genauer 2^31 = 2,147,483,648. Das entspeicht etwas 500 millionen integer Werte. 250 millionen double Werte. Und 83 millionen x,y,z Koordinaten. Das hört sich viel an, aber wenn wir mal ehrlich sind, das ist garnichts. Gerade in der Big Data Zeit rechnet man nicht mehr in GB sondern ehr in PB.

Also, muss man in seiner GUI Anwendung so 10, 20 Zahlen speichern, dann sind die Qt Container alle gut.
Möchte man mehr wissenschaftlich arbeiten, dann nur die std Container. Alles schön trennen und streng zu sich selbst sein, dann stürzen die Programme auch nicht ab :)

20.05.2015

-1 (Bug of the day 5)

Filed under: Allgemein — Tags: , — Thomas @ 19:05

vector vecB;
vecB.resize(vecA.size()-1);

for(size_t i = 0; i < vecA.size(); ++i) {  
  ...
  vecB[i] = value
  ...
}

Na, wer findet ihn?

Bei so etwas findet ich QT's QVector wieder besser als den Standard c++ vector. Qt macht zumindest bei Debug Einstellung eine Bereichsüberprüfung.

Ausser es wird die at() Funktion statt den operator() benutzt. Dann machen beide eine Bereichsüberprüfung. Aber auch hier zeigen sich kleine Unterschiede welche die Philosophie von Qt und cpp Standardlib zeigen.
Qt bietet nur eine cost Version der Funktion at() an. Der Grund liegt wahrscheinlich im intuitiven Verständnis des Codes.
Ein normaler Vector zugriff wie man das seit Jahrzehnten macht geht so:

vec[i] = value;

Das sieht sieht "komisch" aus:

vec.at(i) = value;

Qt für normale Programmierer mit wenig Schmerzen. c++ std für Profis mit viel Schmerzen :D

« Newer PostsOlder Posts »

Powered by WordPress