POV-Ray : Newsgroups : povray.newusers : scientific notation Server Time
3 Oct 2025 07:01:40 EDT (-0400)
  scientific notation (Message 1 to 10 of 10)  
From: kurtz le pirate
Subject: scientific notation
Date: 20 Sep 2025 12:45:13
Message: <68ceda19$1@news.povray.org>
Hello,

Any way to format floating with scientifc notation for use in #debug() 
and/or #write() ?





-- 
kurtz le pirate
compagnie de la banquise


Post a reply to this message

From: Kenneth
Subject: Re: scientific notation
Date: 22 Sep 2025 23:20:00
Message: <web.68d20fdff4db7ec9e83955656e066e29@news.povray.org>
Here's my attempt, using string commands-- which are a bit tricky to implement;
there are a few 'hidden rules' that I had to tease out, particularly for the
strlen(...) and substr(...) functions.

The output is in the form of a #debug.

The code is NOT yet completely finished-- and is certainly not elegant-- but I
wanted to post what I have. It works for all positive and negative floats,
*except* for values between +1.0 and -1.0 -- like .078463. No fatal errors for
those, but their resulting scientific notation output is not yet in the proper
form... like 0.078463e0 instead of 7.8463e-2. I'm still working on that; it's a
question of picking the correct *location* in the array of the value-as-strings,
for placing the added decimal point in the proper place for those. (The solution
probably lies in adding more conditionals in the final #debug section, although
I haven't yet figured out where.) The code does work fine for a zero value
though.

The code needs only two entries from the user: the float value to convert, and
the number of significant digits desired in the output.

//-----------
#declare VAL = 347.19054;
#declare SIGNIFICANT_DIGITS = 5; // MUST BE AT LEAST 1, otherwise the final
// result in #debug returns the wrong e exponential value.

#declare VAL_AS_STRING = str(VAL,0,SIGNIFICANT_DIGITS)
#declare STR_LENGTH = strlen(VAL_AS_STRING);
#declare DEC_POINT = "."

#declare C = 1; // a counter
#while(C <= STR_LENGTH)
#declare SS = substr(VAL_AS_STRING,C,1)
#if(SS=DEC_POINT)
#declare COUNT_AT_DECIMAL_POINT=C; // the decimal point position has been
// found at this position, counting from the left of the value.
#declare C = 1000; // to end the while loop
#else
#declare C = C+1;
#declare COUNT_AT_DECIMAL_POINT=0; // in case there is NO decimal point.
#end // of #if
#end // of #while loop

// The following sections recreate VAL (as a string) with the original
// decimal point eliminated and a new one inserted elsewhere.
#declare TEMP_ARRAY = array[STR_LENGTH]
#declare D = 0; // a counter
#while(D < STR_LENGTH)
#declare TEMP_ARRAY[D]= substr(VAL_AS_STRING,D+1,1)
#declare D = D+1;
#end

// The output:
#debug concat(
"\n",
#for(i,0,STR_LENGTH-1)
 #if(i=COUNT_AT_DECIMAL_POINT-1)
 #declare i = i+1; // gets rid of the current decimal point by skipping it
// in the array.
 #end

TEMP_ARRAY[i],
 #if(i=0 & TEMP_ARRAY[0] != "-")
 DEC_POINT, // adds a new decimal point.
 #else
  #if(i=1 & TEMP_ARRAY[0] = "-")
  DEC_POINT, // or ditto
  #end
 #end
 #end // of #for
 "e",

 #if(TEMP_ARRAY[0] != "-" & COUNT_AT_DECIMAL_POINT !=0)
 str(COUNT_AT_DECIMAL_POINT-2,0,0)
 #else
 #end

 #if(TEMP_ARRAY[0] = "-" & COUNT_AT_DECIMAL_POINT !=0)
 str(COUNT_AT_DECIMAL_POINT-3,0,0)
 #else
 #end
"\n") // end of #debug
// END OF FILE


Post a reply to this message

From: Bald Eagle
Subject: Re: scientific notation
Date: 23 Sep 2025 06:40:00
Message: <web.68d278dbf4db7ec91f9dae3025979125@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:
> Here's my attempt, using string commands-- which are a bit tricky to implement;

I haven't read your code - have an unexpectedly busy morning here....

But why don't you just write a macro that takes your number as an argument, and
determines if its (abs val) is over 10 or under 1.

Then you can just run a loop by multiplying/dividing by 10 until you're in that
range, and then your exponent is the (signed) loop value.

Might be easier.
I recall I did something like this to buffer the str() output for a #debug
stream with spaces to make everything line up nicely.  No idea what scene code
that was in.

- BW


Post a reply to this message

From: Kenneth
Subject: Re: scientific notation
Date: 23 Sep 2025 12:20:00
Message: <web.68d2c61cf4db7ec9e83955656e066e29@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
>
> But why don't you just write a macro that takes your number as an argument, and
> determines if its (abs val) is over 10 or under 1.
>
> Then you can just run a loop by multiplying/dividing by 10 until you're in that
> range, and then your exponent is the (signed) loop value.
>

Well, duh! That was an *excellent* suggestion. Forget my clumsy string-code
version; this one is certainly more compact and easy to grasp. It works with all
float values, as far as I know from many tests. I have included the code itself
and as a macro. The output is again as a #debug message.

I did have to add a slight kludge for an input value of exactly zero; it's
scientific notation initially ended up as 0.00000e-1, which is certainly not
correct. I'm not sure why that occurred in my code; it might be a subtle
'under the hood' error(?) Anyway, zero doesn't really need such notation, from
what I've read; so I eliminated its e exponent altogether. Problem solved! ;-)

---
definition of 'kludge' from Wikipedia:
"A kludge or kluge is a workaround or makeshift solution that is
clumsy, inelegant, inefficient...Its only benefit is that it
rapidly solves an important problem using available resources."
---

The code:

#local VAL = -.00067;
#local SIGNIFICANT_DIGITS =3;
#local ABS_VAL = abs(VAL);

// counters
#local C1 = 0;
#local C2 = 0;
#local C3 = 0;
#local C4 = 0;

#if(ABS_VAL <= 1.0 & ABS_VAL !=0.0 & ABS_VAL != -0.0)
 #while(C4 <= 25) // arbitrary large value
  #if(ABS_VAL < pow(10,C3))
  #local C3 = C3-1;
  #local C4 = C4+1;
  #else
  #local C4 = 1000; // to stop the while loop
  #end
 #end

 #local VAL_1 = VAL/pow(10,(C3));
 #debug concat("\n","VAL_1 as SCI NOTE = ",
 str(VAL_1,0,SIGNIFICANT_DIGITS),"e",str(C3,0,0),"\n")

#else // ABS_VAL > 1.0)
 #while(C2 <= 25) // arbitrary large value
  #if(ABS_VAL > pow(10,C1))
  #local C1 = C1+1;
  #local C2 = C2+1;
  #else
  #local C2 = 1000; // to stop the while loop
  #end
 #end

 #local VAL_2 = VAL/pow(10,(C1-1));
 #debug concat("\n","VAL_2 as SCI NOTE = ",
 str(VAL_2,0,SIGNIFICANT_DIGITS),
 #if(VAL_2 = 0) // a bandaid kludge for a problem when VAL = 0.
 "\n")
 #else
 "e",str(C1-1,0,0),"\n")
 #end

#end

//-------------------
//as a MACRO:
(Note: SD -- significant digits desired in the output)

#macro SCI_NOTA_CONVERS(VAL,SD)
#local ABS_VAL = abs(VAL);
#local C1 = 0;
#local C2 = 0;
#local C3 = 0;
#local C4 = 0;
#if(ABS_VAL <= 1.0 & ABS_VAL !=0.0 & ABS_VAL != -0.0)
 #while(C4 <= 25)
  #if(ABS_VAL < pow(10,C3))
  #local C3 = C3-1;
  #local C4 = C4+1;
  #else
  #local C4 = 1000;
  #end
 #end
 #local VAL_1 = VAL/pow(10,(C3));
 #debug concat("\n","VAL_1 as SCI NOTE = ",
 str(VAL_1,0,SIGNIFICANT_DIGITS),"e",str(C3,0,0),"\n")
#else // ABS_VAL > 1.0)
 #while(C2 <= 25)
  #if(ABS_VAL > pow(10,C1))
  #local C1 = C1+1;
  #local C2 = C2+1;
  #else
  #local C2 = 1000;
  #end
 #end
 #local VAL_2 = VAL/pow(10,(C1-1));
 #debug concat("\n","VAL_2 as SCI NOTE = ",
 str(VAL_2,0,SIGNIFICANT_DIGITS),
 #if(VAL_2 = 0)
 "\n")
 #else
 "e",str(C1-1,0,0),"\n")
 #end
#end
#end // of macro

// using it:
SCI_NOTA_CONVERS(467.00953,8)


Post a reply to this message

From: Bald Eagle
Subject: Re: scientific notation
Date: 23 Sep 2025 13:05:00
Message: <web.68d2d291f4db7ec91398638025979125@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:
> Forget my clumsy string-code
> version; this one is certainly more compact and easy to grasp. It works with all
> float values, as far as I know from many tests. I have included the code itself
> and as a macro. The output is again as a #debug message.

Forget my crummy early-morning loop suggestion.  Just use int(log(abs(num)))

No idea what you're doing in your code,
but try:

#macro SciNot (Num, Precision)
#if (Num = 0)
#local Result = "0\n"
#else
#local Exponent = int(log(abs(Num)));
#local Significand = Num/pow(10, Exponent);
#local Result = concat (str(Significand, 0, Precision), " x 10^", str(Exponent,
0, 0), "\n")
#end // end if
#debug Result
#end // end macro

- BW


Post a reply to this message

From: Kenneth
Subject: Re: scientific notation
Date: 23 Sep 2025 13:45:00
Message: <web.68d2dbc4f4db7ec9e83955656e066e29@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
> try:
>
> #macro SciNot (Num, Precision)
> #if (Num = 0)
> #local Result = "0\n"
> #else
> #local Exponent = int(log(abs(Num)));
> #local Significand = Num/pow(10, Exponent);
> #local Result = concat (str(Significand, 0, Precision), " x 10^", str(Exponent,
> 0, 0), "\n")
> #end // end if
> #debug Result
> #end // end macro
>

(I changed your " x 10^" to "e" )

Yes, it works and is quite elegant, although it's a bit beyond my mental grasp
as to how. I haven't used logarithms since my college days, ha.

Although: For fractional values like .000794, it returns 0.794e-3. Shouldn't it
return 7.94e-4 instead?


Post a reply to this message

From: Bald Eagle
Subject: Re: scientific notation
Date: 23 Sep 2025 14:00:00
Message: <web.68d2def3f4db7ec91398638025979125@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:

> Yes, it works and is quite elegant, although it's a bit beyond my mental grasp
> as to how. I haven't used logarithms since my college days, ha.

log(N) = 10^exponent

which gives you some (usually) non-integer exponent.
But you only want the integer part of that.

then you raise 10 to that power, and divide your original number by that.
That obviously gives you the number to multiply that power of 10 by.
Then you just cobble it all together with concat.

> Although: For fractional values like .000794, it returns 0.794e-3. Shouldn't it
> return 7.94e-4 instead?

I don't have my laptop at hand because "reasons" - so I'm just doing this in
Excel.

Excel has a weird Floor format, so I used Int.

Try using floor().  Or ceil.  Or maybe POV-Ray does weird things and you need to
test your value and then conditionally use one or the other.

I would love an online parser.  :)

- bw


Post a reply to this message

From: Kenneth
Subject: Re: scientific notation
Date: 24 Sep 2025 11:40:00
Message: <web.68d41047f4db7ec9e83955656e066e29@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
>
> Try using floor().  Or ceil.  Or maybe POV-Ray does weird things and you
> need to test your value and then conditionally use one or the other.
>

FIXED for fractional values, by using floor:

---------
#macro SciNot (Num, Precision)
#if (Num = 0)
#local Result = "0\n"
#else
#local Exponent = int(floor(log(abs(Num))));
#local Significand = Num/pow(10, Exponent);
#local Result = concat (str(Significand, 0, Precision), "e", str(Exponent, 0,
0), "\n")
#end
#debug Result
#end
---------

Example:
#declare MY_VAL = -.00674;

// the macro:
SciNot (MY_VAL, 3)

returns  -6.740e-3

-----------
BTW, this will also work:
#local Exponent = int(log(#if(Num < 1 & Num > -1) .1* #else #end abs(Num)));


Post a reply to this message

From: Bald Eagle
Subject: Re: scientific notation
Date: 24 Sep 2025 12:00:00
Message: <web.68d414cdf4db7ec91398638025979125@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:

> #local Exponent = int(floor(log(abs(Num))));

int(floor()) is redundant.
just use floor ()

floor(A)
Floor of A. Returns the largest integer less than A. Rounds down to the next
lower integer.

https://wiki.povray.org/content/Reference:Numeric_Expressions

> BTW, this will also work:
> #local Exponent = int(log(#if(Num < 1 & Num > -1) .1* #else #end abs(Num)));

:O

- bw


Post a reply to this message

From: Kenneth
Subject: Re: scientific notation
Date: 24 Sep 2025 12:10:00
Message: <web.68d41766f4db7ec9e83955656e066e29@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
> "Kenneth" <kdw### [at] gmailcom> wrote:
>
> > #local Exponent = int(floor(log(abs(Num))));
>
> int(floor()) is redundant.
> just use floor ()
>

Yes indeedee it does work. I should have seen that :-|

#local Exponent = floor(log(abs(Num)));


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.