Formatted output with leading zeros in Fortran - formatting

I have some decimal numbers that I need to write to a text file with leading zeros when appropriate. I've done some research on this, and everything I've seen suggests something like:
REAL VALUE
INTEGER IVALUE
IF (VALUE.LT.0) THEN
IVALUE = CEILING(VALUE)
ELSE
IVALUE = FLOOR(VALUE)
ENDIF
WRITE(*,1) IVALUE, ABS(VALUE)-ABS(IVALUE)
1 FORMAT(I3.3,F5.4)
As I understand it, the IF block and ABS parts should allow this to work for all values on -100 < VALUE < 1000. If I set VALUE = 12.3456, the code above should produce "012.3456" as the output, and it does. However if I have something like VALUE = -12.3456, I'm getting "(3 asterisks).3456" as my output. I know the asterisks usually shows up when there are not enough characters provided for in the FORMAT statement, but 3 should be enough in this example (1 character for the "-" and two characters for "12"). I haven't tested this yet with something like VALUE = -9.876, but I'd expect the output to be "-09.8760".
Is there something wrong in my understanding of how this works? Or is there some other limitation of this technique that I'm violating?
UPDATE: Okay I've looked into this some more, and it seems to be a combination of a negative value and the I3.3 format. If VALUE is positive and I have the I3.3, it will put leading zeros as expected. If VALUE is negative and I only have I3 as my format, I get the correct value output, but it will be padded with spaces before the negative sign instead of padded with zeros after the negative (so -9.8765 is output as " -9.8765", but that leading space breaks what I'm using the .txt file for, so it's not acceptable).

Tho problem is with your integer data edit descriptor. With I3.3 you require at least 3 digits and the field width is only 3. There is no place for the minus sign. Use I4.3 or, In Fortran 95 and above, I0.3.
Answer to your edit: Use I0.3, it uses the minimum number of characters necessary.
But finally, you just probably want this: WRITE(*,'(f0.3)') VALUE

Of course, I could get what I'm looking for by changing it up a little bit to
REAL VALUE
INTEGER IVALUE
IF (VALUE.LT.0) THEN
WRITE(*,1) FLOOR(ABS(IVALUE)), ABS(VALUE)-FLOOR(ABS(VALUE))
1 FORMAT('-',I2.2,F5.4)
ELSE
WRITE(*,2) FLOOR(VALUE), ABS(VALUE)-FLOOR(BS(VALUE))
2 FORMAT(I3.3,F5.4)
ENDIF
But this feels a lot clunkier, and in reality I'm going to try to be writing multiple values in the same line, which will lead to really messy IF blocks or complex cursor movement, which I'd like to avoid if at all possible.

as another way to skin the cat.. I'd prefer not to do arithmatic on the data at all but just work on the format:
character*8 fstring/'(f000.4)'/
val=12.34
if(val.gt.1)then
write(fstring(3:5),'(i0)')6+floor(log10(val))
elseif(val.lt.-1)then
write(fstring(3:5),'(i0)')7+floor(log10(-val))
elseif(val.ge.0)
write(fstring(3:5),'(i0)')6
else
write(fstring(3:5),'(i0)')7
endif
write(*,fstring)val
just for fun with modern fortran that supports character functions you can roll that up in a function and end up with a construct like this:
write(*,'('//fstring(val1)//','//fstring(val2)//')')val1,val2

Related

RAND() not consistently generating the right length value

I've got the following code in place with the idea being that I need a 30 character random number generated each time the stored procedure is called and the odd thing is that in most cases it works as intended but in other seemingly random cases it will only generate a 28 character random number.
'\\xxx-servername\folder\'+
CAST(CAST((RAND()*1000000000000000000000000000000) as decimal(30))as varchar(30)) +
RAM.AccountNumber+HRMRN.PrefixMedicalRecordNumber+'ESTIMATE N00001'+
REPLACE(CONVERT(VARCHAR(12),ISNULL(HRM.Birthdate,HRM.BirthdateComputed),111),'/','')+HRM.Sex+
REPLACE(CONVERT(VARCHAR(12),GetDate(),111),'/','')+LEFT(REPLACE(CONVERT(VARCHAR(12),GetDate(),108),':',''),4)+'.PDF' as [CPFileName]
Hope maybe someone can offer some advice because I'm at a loss...
I suspect that your system is automatically removing leading zeros. You can either re-insert those zeros yourself, or else construct your number using something like:
number <- ""
number.append(randomDigit(1,9))
repeat 29 times
number.append(randomDigit(0,9))
end repeat
That guarantees that you do not get a leading zero.

How can I set a minimal amount of numbers after the decimal dot (0.9=>0.90)

I'm using google bigquery, and a column has values I want to round. If I do, and the rounded value ends in a zero, the zero is not displayed.
I've tried the function FORMAT, which apparently has some .number function, but I have no idea how to use it. Whenever I include any 2 things separated by a comma inside its brackets, it complains that it only takes 1 value.
You would use FORMAT() with the precision specifier. For four decimal places always -- including zeros:
select format('%.4f', 1.23)
If the BQ documentation does not answer your questions, I find that that the function seems to be inspired by the classic C printf()/sprintf() functions.
Unaware if in BigQuery (haven't used it ever) there is a better way I guess this will fix your problem since I just tried it in their console.
Cast your float to a string and then check if your last digit is a 0. In case it's not add it:
SELECT case when RIGHT(cast(0.9 as string), 1) <> '0' then cast(0.9 as string)+'0' else cast(0.9 as string) end as FormattedNumber

Is format ####0.000000 different to 0.000000?

I am working on some legacy code at the moment and have come across the following:
FooString = String.Format("{0:####0.000000}", FooDouble)
My question is, is the format string here, ####0.000000 any different from simply 0.000000?
I'm trying to generalize the return type of the function that sets FooDouble and so checking to make sure I don't break existing functionality hence trying to work out what the # add to it here.
I've run a couple tests in a toy program and couldn't see how the result was any different but maybe there's something I'm missing?
From MSDN
The "#" custom format specifier serves as a digit-placeholder symbol.
If the value that is being formatted has a digit in the position where
the "#" symbol appears in the format string, that digit is copied to
the result string. Otherwise, nothing is stored in that position in
the result string.
Note that this specifier never displays a zero that
is not a significant digit, even if zero is the only digit in the
string. It will display zero only if it is a significant digit in the
number that is being displayed.
Because you use one 0 before decimal separator 0.0 - both formats should return same result.

SSRS- Conditional formatting with Percents and numbers

In my mind this should be easy.. I have spent a good bit of time trying to get this right
Problem-
I have 1 data set that returns whole numbers as well as percents. What I am looking for is a formatting step to work and add the correct suffix (x100+% when % or nothing)
Here is what I have but don't get consistent results
=iif(Fields!Mid_Size.Value<1,Format(Fields!Mid_Size.Value,"P"),Format(Fields!Mid_Size.Value,"#"))
The raw data looks like:
Alpha Mid-Size
11 49
0.0718954248366013 0.320261437908497
Anyone have any ideas?
Try this:
=iif(Fields!Mid_Size.Value<1,FormatPercent(Fields!Mid_Size.Value,0),Format(Fields!Mid_Size.Value,"#"))
This uses the FormatPercent function. The '0' is for no decimal places; you can set that to however many you want.

What does %2.6f do in Objective C String Formatting?

Based on Apple's documentation here: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Strings/Articles/FormatStrings.html
It's pretty easy to understand the number to the right of the decimal point is the number of digis will be rounded up...
For example, %1.2f, 123456.123456 will turn out 123456.12 and %1.4f will turn out 123456.1234...
But it looks like the number to the left of decimal does nothing.
I tried changing the number to whatever I can think of, nothing happened.
What does it do?
The number before the decimal point in the format is called the format string's width. That is, if the resultant string would involves less characters than its width, it will be left-padded with blank spaces. You don't see any change because you either aren't using a high enough number (try something ridiculous like 100 or 200), or don't have a means of properly seeing your whitespace.