Ein Lernprogramm in C [] (Ein Lernprogramm in C), Lektion, Seite 723722
https://www.purl.org/stefan_ram/pub/lernprogramm_c (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C-Kurs

Ein Lernprogramm in C 

main.c
/** @file main.c
@brief Choose one of several questions with a given probability. */

#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/* #define DEBUG 1 */

/** @def DEBUG_PRINT_DOUBLE( text, number )
@brief prints a text and a number in DEBUG mode. */
#ifdef DEBUG
#define DEBUG_PRINT_DOUBLE( text, number ) \
printf( text "%g\n", number );
#endif
#ifndef DEBUG
#define DEBUG_PRINT_DOUBLE( text, number )
#endif

/** @brief a propensity and a question-answer pair.
@details the propensity gives the relative frequency of
this entry (in relation to the sum of all propensities of
entries in a set). */
struct entry
{ double propensity;
char const * const question;
char const * const answer; };

/** @brief a list of entries with their propensities and texts. */
struct entry entry[]=
{ { 2.0, "meaning of 'elusive'",
"difficult to find, describe, remember, or achieve" },
{ 1.0, "meaning of 'reprimand'",
"speak to someone angrily or seriously for doing something" }};

/** @brief print the question of the component with the given
offset from the array »entry«.
@param i the offset of the component whose question is to be
printed */
void print_question( int const i )
{ puts( entry[ i ].question ); }

/** @brief print the answer of the component with the given
offset from the array »entry«.
@param i the offset of the component whose question is to be
printed */
void print_answer( int const i )
{ puts( entry[ i ].answer ); }

/** @brief the sum of all propensities.
@details this is set by calculate_the_sum_of_all_the_propensities
and used by calculate_the_summed_propensities. */
double sum;

/** @brief the type for a counter that wants to enumerate the
offset of all entries of the entry array. */
typedef size_t counter_t;

/** @brief the size of the entry array. */
counter_t const entry_length = sizeof entry / sizeof 0[ entry ];

/** @brief the entry at position p in this arrays contains the
sum of all probabilities given by the array entry up to p.
@details A probability is calculated from the propensity by
normalizing it so that the sum of a probabilities is 1.
@details This is set in calculate_the_summed_propensities and
used in print_the_next_random_entry. */
double summed[ ( int )( sizeof entry / sizeof 0[ entry ])];

/** @brief this calculates the sum of all the propensities
of the entry array and stores it in the variable sum. */
void calculate_the_sum_of_all_the_propensities( void )
{ sum = 0.0;
for( counter_t i = 0; i < entry_length; ++i )
sum += entry[ i ].propensity;
DEBUG_PRINT_DOUBLE( "sum = ", sum ); }

/** @brief this calculates the values in the array
summed so that a value at the position p contains the
sum of the probabilities of all the entries of the
array »entry« up to the position p. */
void calculate_the_summed_propensities( void )
{ double sumsofar = 0.0;
for( counter_t i = 0; i < entry_length; ++i )
{ double const probability = entry[ i ].propensity / sum;
sumsofar += probability;
summed[ i ]= sumsofar;
DEBUG_PRINT_DOUBLE( "sumsofar = ", sumsofar ); }
assert( fabs( sumsofar - 1.0 )< 1e-9 ); }

/** @brief returns a uniformly-distributed double value i,
with min <= i < top and with a number of rand() calls
that is smaller than a certain small number (like 4)
that depends on top-min and RAND_MAX.
@param min the minimum result
@param top the maximum result (exclusive)
@return a random number between min (inclusive)
and max (exclusive) */
double doublenumber( double min, double top )
{ { double step; do
{ step =( top - min )/( RAND_MAX + 1. );
min = min + rand() * step; top = min + step; }
while( min < top ); } return min; }

/** @brief returns a uniformly-distributed integral number i,
with 0 <= i < 1 and with a number of rand() calls
that is smaller than a certain small number (like 4)
that depends on top-min and RAND_MAX.
@return a random number between 0 (inclusive)
and 1 (exclusive) */
double random_number_between_0_and_1( void )
{ return doublenumber( 0, 1 ); }

/** @brief returns a random offset from the array »entry«.
@details when this function is called many times, each offset
of the array »entry« is returned with a frequency corresponding
to the probability of its propensity. */
counter_t next_random_offset( void )
{ double const number = random_number_between_0_and_1();
DEBUG_PRINT_DOUBLE( "number = ", number );
for( counter_t i = 0; i < entry_length; ++i )
if( summed[ i ] > number ){ return i; break; }
return entry_length > 1 ? number < 0.5 ? 0 :
entry_length - 1 : 0; }

/** @brief returns a random number from a measurement of some
random process.
@details The overall quality of randomness of this function is
not specified. In the worst case it might always return the same
number. */
unsigned int entropy( void )
{ return ( unsigned int )time( 0 )*( unsigned int )time( 0 )+
( unsigned int )time( 0 ); }

int main( void )
{
srand( entropy() * entropy() + entropy() );
rand(); rand(); rand();

assert( entry_length > 1 );
assert( entry_length < INT_MAX );

calculate_the_sum_of_all_the_propensities();
calculate_the_summed_propensities();

for( int i = 0; i < 10; ++i )
{ counter_t const o = next_random_offset();
print_question( o );
getchar();
print_answer( o );
puts( "----------------------------------------\n\n" ); }}

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723722 stefan_ram:723722 Ein Lernprogramm in C Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723722, slrprddef723722, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/lernprogramm_c