Just a Couple of Quick Questions


#1

So I’ve recently come across some Modula 2 code that I wrote ages ago and realised that a small part of it might be worth converting to NWScript. However, not being that into the actual under the hood way that NWScript actually works, I need to ask a couple of questions.

Question 1 is probably the easiest to answer. The code that I wrote involves some pre-calculated numbers. The only thing is that they were written for double precision floating point numbers (i.e. 64 bit as opposed to NWScript’s 32 bit). As an illustration (i.e. not considering converting this actual line) of what I am talking about the following constant declaration -

ReciprocalOfPI = 0.31830988618379067154;   (* 1 / PI *)

All I need to know is how many digits can I safely lose from the right of such numbers.

Now to my other question. Are pseudo arrays the best solution for storing related data where the actual number of pieces of data is unknown until run time?

Thanks.

FWIW I don’t know if anyone has a use for them but as an exercise in making sure that I could remember enough about Modula 2 to be able to do the conversion, I did these little functions.

int GCD(int C, int D)
{
    if(C == 0) 
       return D; 
    else if(D == 0 || C == D) 
       return C; 
    else
        return GCD(D, C % D); // Eek! Recursion
}

int GreatestCommonDivisor(int A, int B)
{
    if(A < 0 || B < 0) // only works for positive numbers
        return -1;
        
    if(A < B) //swap them using bitwise Exclusive Or as they are ints
    {
        A ^= B;
        B ^= A;
        A ^= B;
    }
    
    return GCD(A, B);
}

int LowestCommonMultiple(int M, int N)
{
    if(M < 0 || N < 0) // only works for positive numbers
        return -1;
        
    return M / GreatestCommonDivisor(M, N) * N;
}

Note if an error occurs they return -1.

TR


#2

Not sure if you are asking how to represent that or what impact on stability of your original code will single-precision arithmetic have (not a good one), but you can simply do this:

const float ReciprocalOfPI = 0.31830988618379067154; // NWScript

And the game will convert that to its own float, whatever that may be.

What’s related data? Like a key = val dictionary pair? Or do you mean homogeneous data stream?


#3

As far as the numbers go what I am asking is how much I can truncate the value so that people reading the script do not get the wrong idea about the accuracy of those numbers when used in NwN. As I say the numbers that I want to use are all pre-calculated but to double precision floating point which are not part of NWScript.

I’ll be using structs to hold data related to what I am doing. You could say that each struct represents one data item and I want to be able store and retrieve an arbitrary number (determined at run time) of them.

TR


#4

i think NwScript (float) is good to 7 decimal places, TR

but i’m not certain 'cause I haven’t looked into/tested the mantissas etc etc.

generally I trust/rely on 5 decimal precision for sure – probly 6 and maybe 7

although … note this declaration in nwn2

// Convert fFloat into a string.
// - nWidth should be a value from 0 to 18 inclusive.
// - nDecimals should be a value from 0 to 9 inclusive.
string FloatToString(float fFloat, int nWidth=18, int nDecimals=9);

#5

Don’t truncate anything. Provide constants with highest accuracy possible - the game will take it from there. Just put a message in the readme about 32-bit float issues. Most people will use constant as is rather than open the file and look at the value. But if you must, do as @kevL_s suggests and use the output of FloatToString(ReciprocalOfPI, 0, 9). Your biggest enemy is rounding anyway.

EDIT: This quote from nwscript.nss might suggest what devs thought about this issue:

float  PI = 3.141592;

Too bad NWN has no pointers exposed in API. You may need to serialize contents of a struct to store it. I’m working on something that may be helpful here. Give me a week max.